set/change size of InlineKeyboardMarkup buttons like ReplyKeyboardMarkup - python-3.5

I have 4 keys in my telegram bot api with InlineKeyboardMarkup,
but when i send it for android client size of buttons is too small that user can see.In web client of telegram these icons is ok and have very well size !
Is there any way to set buttons size in InlineKeyboardMarkup like ReplyKeyboardMarkup and resize_keyboard parameter?
or customize these buttons size and ... ?
class Ctmp: pass
ctobj = Ctmp()
ii = 0
a = []
for k, v in ddd.items() :
if ( len(k) > 0 and len(v) > 0 ) :
print(k, v)
setattr(ctobj, 'repkey'+ str(i), InlineKeyboardButton(text= str(v), callback_data=str(k), resize_keyboard=True))
a.append( getattr(ctobj, 'repkey' + str(i)) )
++ii
repl = InlineKeyboardMarkup([a])
bot.sendMessage(chat_id= dd.get("chatid", None), text="/", reply_markup=repl)

The size of the buttons automatically gets adapted to the content of the buttons. You can't change the size of the buttons yourself.
On certain devices there are problems when the content is not completely trimmed.
So:
Make sure you are setting a Button text
Make sure all leading and trailing blanks, new lines are removed.

Related

Python Keyboard module detects the pressed key more than once

I'm trying to make a keylogger with the 'Keyboard' module in Python, the troubble is that the read_key() function is returning the same pressed key many times.
import keyboard as kb
cadena = ''
while True:
key = kb.read_key()
if len(key) == 1:
cadena +=key
print(cadena)
I just wrote "Hello world"
but this code returns:
h
hh
hhe
hhee
hheel
hheell
hheelll
hheellll
hheellllo
hheelllloo
hheelllloow
hheelllloowo
hheelllloowow
hheelllloowowo
hheelllloowowor
hheelllloowoworr
hheelllloowoworrl
hheelllloowoworrll
hheelllloowoworrlld
hheelllloowoworrlldd
You can use keyboard.record to record all keyboard activity until a specified key is pressed. After this you can either replay the activity or print particular events (e.g. down press events):
import keyboard
text = ""
rec = keyboard.record(until='Enter')
# Either this
keyboard.play(rec)
# Or this
for event in rec:
if event.event_type == "down":
text += event.name
print(text)

InlineKeyboardMarkup Telegram bot (pyTelegramBotAPI)

I am making a bot on pyTelegramBotAPI, I need to generate a list of buttons and write it into the keyboard (So that there are 5 buttons in a row). How should I do it? I have a code:
def start(message):
markup = types.InlineKeyboardMarkup()
buttons = []
for i in range(-12, 15):
if i < 0:
button = types.InlineKeyboardButton(f'{i}', callback_data=f'{i}')
elif i == 0:
button = types.InlineKeyboardButton(f'±{i}', callback_data=f'{i}')
else:
button = types.InlineKeyboardButton(f'+{i}', callback_data=f'{i}')
buttons.append(button)
if len(buttons) == 5:
# here i want to add buttons in a row
bot.send_message(message.chat.id, f'Здравствуйте, <b>{message.from_user.first_name}</b>. Для начала необходимо настроить часовой пояс. Выберите разницу во времени относительно UTC (Москва: "+3", Владивосток: "+10", Исландия: "+1")', parse_mode='html', reply_markup=markup)```
I can advise you to create a separate module responsible for keyboards.
example of modules
This way you can separate the logic of handlers from the logic of keyboards.
As torrua wrote earlier, you can use the keyboa (how to use keyboa) library.
or write the functions yourself to create keyboards and buttons in it.
What you need to know for this:
telebot.types.InlineKeyboardMarkup() # creates an empty keyboard.
telebot.type.InlineKeyboardButton() # creates a button for the keyboard created earlier.
.row() # determines the position of the buttons in the keyboard.
example of function to get keyboards
You can do it easy with keyboa:
from keyboa import Keyboa
def start():
buttons = []
for i in range(-12, 15):
if i < 0:
button = (f'{i}', i)
elif i == 0:
button = (f'±{i}', i)
else:
button = (f'+{i}', i)
buttons.append(button)
keyboard = Keyboa(items=buttons, items_in_row=5).keyboard
bot.send_message(message.chat.id, f'Здравствуйте, <b>{message.from_user.first_name}</b>. Для начала необходимо настроить часовой пояс. Выберите разницу во времени относительно UTC (Москва: "+3", Владивосток: "+10", Исландия: "+1")', parse_mode='html', reply_markup=keyboard)```

How to reset a FileBrowse or set a FileBrowse to a given path in PySimpleGUI?

I am using PySimpleGUI. I have the following snippet:
import PySimpleGUI as sg
layout = [[sg.Text('File', size=(4, 1)), sg.Input(key="-FILE-", default_text="browse!", size=(128, 2)), sg.FileBrowse()],
[sg.Button("Select file", key="-SELECT_FILE-"), sg.Button("Cancel", key="-SELECT_CANCEL-")]]
window = sg.Window('test reset browse', layout)
while True:
event, values = window.read()
if event == "-SELECT_CANCEL-":
window.FindElement("-FILE-").Update("cancel!")
# I want to reset also the FileBrowse initial path
if event == sg.WIN_CLOSED:
break
Any idea on how to reset / set to a given path the FileBrowse when canceling (comment line)?
Or formulated another way:
given that browse has been used to select a path
given that the cancel button is pressed
how to either:
reset the path to the initial path that was proposed the very first time the browsing was started
OR
how to set by hand the new initial path for the next browsing
?
There is a way to do this, as per this github issue answer from the creator of PySimpleGUI themself.
It turns out, if we add a key to your sg.FileBrowse object like so:
sg.FileBrowse(key="-FILEBROWSE-",)
then one may simply write
window["-FILEBROWSE-"].InitialFolder = r"C:\\"
obviously replacing the string with whatever path is desired. This, for example, will set the initial folder to the C drive.
See your full code with my changes:
layout = [
[
sg.Text('File', size=(4, 1)),
sg.Input(key="-FILE-", default_text="browse!", size=(128, 2)),
sg.FileBrowse(key="-FILEBROWSE-",) # Add key here
],
[
sg.Button("Select file", key="-SELECT_FILE-"),
sg.Button("Cancel", key="-SELECT_CANCEL-")
]
]
window = sg.Window('test reset browse', layout)
while True:
event, values = window.read()
if event == "-SELECT_CANCEL-":
window.FindElement("-FILE-").Update("cancel!")
# I want to reset also the FileBrowse initial path
# Set initial folder here
window["-FILEBROWSE-"].InitialFolder = r"C:\\"
if event == sg.WIN_CLOSED:
break
Here are the default values of Sg.FileBrowse. As you can see there is an initial_folder option you can use. I'd suggest you use this.
def FileBrowse(button_text='Browse', target=(ThisRow, -1), file_types=(("ALL Files", "*.*"),), initial_folder=None,
tooltip=None, size=(None, None), auto_size_button=None, button_color=None, change_submits=False,
enable_events=False, font=None, disabled=False,
pad=None, key=None, metadata=None):

Qt3D Window and two layers, viewports, layerfilters, etc

I want to code a Qt3DWindow where I would have two QLayer-s, QLayerFilter-s, QViewport-s, etc. I need this because I want to render entities in QViewport 1 in a usual way and entities in QViewport 2 always visible (even when they are actually behind entities 1).
Here is my code:
class Window(Qt3DExtras.Qt3DWindow):
def __init__(self):
super().__init__()
self.root_entity = Qt3DCore.QEntity()
self.entity_1 = Qt3DCore.QEntity(self.root_entity)
self.entity_2 = Qt3DCore.QEntity(self.root_entity)
self.setRootEntity(self.root_entity)
# some other code
self.surselector = Qt3DRender.QRenderSurfaceSelector()
self.surselector.setSurface(self)
# Viewport 1
self.viewport_1 = Qt3DRender.QViewport(self.surselector)
self.layerfilter_1 = Qt3DRender.QLayerFilter(self.viewport_1)
self.layer_1 = Qt3DRender.QLayer(self.entity_1)
self.entity_1.addComponent(self.layer_1)
self.layer_1.setRecursive(True)
self.layerfilter_1.addLayer(self.layer_1)
self.cameraSelector_1 = Qt3DRender.QCameraSelector(self.layerfilter_1)
self.clearBuffers_1 = Qt3DRender.QClearBuffers(self.cameraSelector_1)
self.cameraSelector_1.setCamera(self.camera())
self.clearBuffers_1.setBuffers(Qt3DRender.QClearBuffers.AllBuffers)
# Viewport 2
self.viewport_2 = Qt3DRender.QViewport(self.surselector)
self.layerfilter_2 = Qt3DRender.QLayerFilter(self.viewport_2)
self.layer_2 = Qt3DRender.QLayer(self.entity_2)
self.entity_2.addComponent(self.layer_2)
self.layer_2.setRecursive(True)
self.layerfilter_2.addLayer(self.layer_2)
self.cameraSelector_2 = Qt3DRender.QCameraSelector(self.layerfilter_2)
self.clearBuffers_2 = Qt3DRender.QClearBuffers(self.cameraSelector_2)
self.cameraSelector_2.setCamera(self.camera())
# The line below causes that no entity appears
self.clearBuffers_2.setBuffers(Qt3DRender.QClearBuffers.AllBuffers)
# The code below is what make viewport 2 / layer 2 / layerfilter 2 different from view port 1 / etc.
self.rendstate_2 = Qt3DRender.QRenderStateSet(self.clearBuffers_2)
self.rendstate_2.setParent(self.clearBuffers_2)
depth = Qt3DRender.QDepthTest()
depth.setDepthFunction(Qt3DRender.QDepthTest.LessOrEqual)
self.rendstate_2.addRenderState(depth)
self.setActiveFrameGraph(self.surselector)
If I understand correctly you want both viewports be drawn over each other (i.e. not in left and right half), while the first one draws all normal entities and the second one the ones that are always visible.
First of all, I think you don't need the viewports. Qt defaults this to the rectangle (0, 0, 1, 1) if none is present, but I'm not sure about this.
The actual issue is this line
self.clearBuffers_2.setBuffers(Qt3DRender.QClearBuffers.AllBuffers)
because here you delete the color buffer as well, which deletes everything the first viewport rendered. Try setting it to Qt3DRender.QClearBuffers.DepthBuffer. This only clears your depth buffer.The entites of the second viewport will be drawn ontop of the rendering of the first viewport.

Error using checkmouse

I'm trying to use checkmouse in order to undraw something from my window. When someone clicks the button it should undraw the text and write something else. I'm using checkMouse and getX() and getY() to do this but i keep receiving this error that states:
File "C:\Users\User\Documents\python\project2.py", line 71, in panel
if (clicknew.getX()>90 and clicknew.getX()<210) and (clicknew.getY()>35 and clicknew.getY() < 0):
AttributeError: 'NoneType' object has no attribute 'getX'
this code that i have done so far is as follows:
from graphics import *
#creating the game panel window
def panel():
#grey window, with coordinates flipped, with banners etc
win = GraphWin("Start Panel", 300,200)
win.setCoords(0,0,300,200)
win.setBackground("light grey")
#drawing the BoilerMazer banner with text
boilermazer = Rectangle(Point(0,200),Point(300,160))
boilermazer.setFill("white")
boilermazer.draw(win)
#text inside
banner1 = Text(Point(150,180),"BoilerMazer")
banner1.setStyle("bold")
banner1.setSize(20)
banner1.draw(win)
#initial game panel is going to have two buttons and a top scores object
#top score "screen"
toprec = Rectangle(Point(60,140),Point(240,50))
toprec.setFill("white")
toprec.draw(win)
#text inside toprec
topscores = Text(Point(150,130),"TOP SCORES")
topscores.setSize(8)
topscores.draw(win)
border = Text(Point(150,120),"======")
border.draw(win)
bigmac = Text(Point(150,110),"Big Mac 21")
bigmac.setSize(8)
bigmac.draw(win)
tt = Text(Point(150,90),"T.T 23")
tt.setSize(8)
tt.draw(win)
cshell = Text(Point(150,75),"C-Shell 25")
cshell.setSize(8)
cshell.draw(win)
macmac = Text(Point(150,55),"MacMac 27")
macmac.setSize(8)
macmac.draw(win)
#new player button that will eventually be clicked
new1 = Point(90,35)
new2 = Point(210,0)
newrec = Rectangle(new1,new2)
newrec.setFill("chartreuse2")
newrec.draw(win)
#new player button text
newplayer = Text(Point(150,18),"NEW PLAYER")
newplayer.draw(win)
#reset button
resetrec = Rectangle(Point(240,35),Point(300,0))
resetrec.setFill("red")
resetrec.draw(win)
#resettext
reset = Text(Point(270,18),"RESET")
reset.draw(win)
#secondary panel window is the game panel after they click new player
#set up points that we check between for the new player button first
#setting up the checkmouse
clicknew = win.checkMouse()
if (clicknew.getX()>90 and clicknew.getX()<210) and (clicknew.getY()>35 and clicknew.getY() < 0):
newplayer.undraw()
you can find the graphics window here:http://mcsp.wartburg.edu/zelle/python/graphics.py
I don't understand what I'm doing wrong, is there some other method that I'm supposed to be using? Thanks for your help
According to the docs, checkMouse() returns None if no mouse click has been detected priorly. So that seems to be the case.
You could put a loop around the call to checkMouse and keep checking if clicknew is not None and only in that case go on in your program. But maybe there's a better way...
UPDATE:
Example:
while True:
clicknew = win.getMouse()
if clicknew:
break
else:
time.sleep(0.1) # avoid busy waiting
# clicknew is set now => use it

Resources