Physical button interacting with tkinter button widget - button

I'm making an app to run with my Raspberry Pi with Tkinter GUI. The app allready runs well. Now I want to use 2 physical buttons wired to GPIOS that interact with two of the buttons widgets I have in the app. Thanks to helpers in forums I found the way to do it as You can see in the code. But now I need to disabled in some way the physical button in order to avoid accidental push meanwhile the scripts run, as I can easly do with the widgets. I've been googling a lot but I din not found any example of whaT i need. Can some one give me orientation about the method to obtain this. Thanks in advance.
from Tkinter import *
import RPi.GPIO as GPIO
root = Tk()
root.geometry("320x480")
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
GPIO.setup(18,GPIO.IN,pull_up_down=GPIO.PUD_UP)
shootdelay = 12 #12
shootinterval = 7#7
shootnumber = 5#12
videodelay = 3
selft = 5
newset = 0
endvideo = 5
intertext = "(D:" + str(shootdelay) + ")(I:" + str(shootinterval) + ")(T:" + str(shootnumber) + ")"
flagselftim = 0
flagvideo = 0
videosetmode = 0
flagsetings = 0
flagcancel = 0
flagnewset = 0
secDelay = shootdelay
secInterv = shootinterval
secSelftim = selft
secvideo = videodelay
remainshots = shootnumber
secshoots = shootnumber - 1
seccompte = 0
readyshoots =
class intervalometer:
def __init__(self, master):
self.textBox = Text(root, height=1, width=1, relief=SUNKEN, font=('arial narrow', 17, 'normal'), bg="green",
fg="white")
self.textBox.grid(row=1, column=1, padx=3, pady=2, sticky=NSEW)
self.textBox.insert(END, "READY")
self.botshoot = Button(root, width=18, font=('arial narrow', 19, 'normal'), text="START",
activebackground="#00dfdf")
self.botshoot.grid(row=4, rowspan=2, column=0, columnspan=2, ipady=15, pady=2, sticky=NSEW)
self.botshoot.configure(command=self.start)
self.botStop = Button(root, heigh=2, font=('arial', 18, 'normal'), text="STOP/RESET", activebackground="red")
self.botStop.grid(row=13, rowspan=3, column=0, pady=1, sticky=NSEW)
self.botStop.configure(state=DISABLED, command=self.stop)
self.botQuit = Button(root, width=3, font=('arial', 18, 'normal'), text="QUIT", activebackground="red",
state=NORMAL)
self.botQuit.grid(row=13, rowspan=3, column=1, pady=1, sticky=NSEW)
self.botQuit.configure(command=self.closewindow)
GPIO.add_event_detect(18, GPIO.RISING, callback=self.start, bouncetime=200)
def start(self, *args, **kwargs):
global flagselftim
self.count = 0
self.cancel_id = None
self.botshoot.configure(state=DISABLED)
self.botStop.configure(state=NORMAL)
self.botQuit.configure(state=DISABLED)
self.start_shoot_delay()
def stop(self):
global secDelay
global secSelftim
global selft
global flagvideo
global videosetmode
global secvideo
global remainshots
global secInterv
global readyshoots
flagvideo = 0
videosetmode = 0
secDelay = shootdelay
secInterv = shootinterval
secvideo = videodelay
selft = 5
secSelftim = selft
remainshots = shootnumber
readyshoots = 1
if self.cancel_id is not None:
self.textBox.after_cancel(self.cancel_id)
self.cancel_id = None
self.textBox.insert(END, 0)
self.textBox.delete("1.0", END)
self.botshoot.configure(text="START")
self.botshoot.configure(state=NORMAL)
self.botStop.configure(state=DISABLED)
self.botQuit.configure(state=NORMAL)
self.textBox.insert(END, "READY")
self.textBox.configure(font=('arial narrow', 17, 'normal'), bg="green", fg="white")
def closewindow(self):
root.destroy()
def start_shoot_delay(self):
global secDelay
if secDelay > 9:
contador = " " + str(secDelay)
else:
contador = " " + str(secDelay)
self.textBox.delete("1.0", END)
self.textBox.configure(font=('arial narrow', 17, 'normal'), bg="red", fg="white")
self.botshoot.configure(state=DISABLED)
if self.count < shootdelay:
self.count += 1
self.textBox.insert(END, contador)
self.cancel_id = self.textBox.after(1000, self.start_shoot_delay)
secDelay -= 1
else:
self.count = 0
secDelay = shootdelay
self.start_shoot_interval()
def start_shoot_interval(self):
global secInterv
if remainshots == shootnumber:
self.start_shootings()
else:
if secInterv > 9:
contador = " " + str(secInterv)
else:
contador = " " + str(secInterv)
self.textBox.delete("1.0", END)
self.textBox.configure(font=('arial narrow', 17, 'normal'), bg="red", fg="white")
if self.count < shootinterval:
self.count += 1
self.textBox.insert(END, contador)
self.cancel_id = self.textBox.after(1000, self.start_shoot_interval)
secInterv -= 1
else:
self.count = 0
secInterv = shootinterval
self.start_shootings()
def start_shootings(self):
global remainshots
global videosetmode
global readyshoots
global secSelftim
global selft
remainshots -=1
if secSelftim <5:
txtremain = "SHOOTING = " + str(1) + "/" + str(1)
else:
txtremain = "REMAINING = " + str(remainshots) + "/" + str(shootnumber)
print "BEEP shoot nr",readyshoots, "av", shootnumber
readyshoots +=1
if remainshots >0:
self.start_shoot_interval()
else:
print "BEEP-BEEP-BEEP : end of roll"
self.etstatus.configure(text="END OF ROLL")
root.update_idletasks()
root.after(500)
readyshoots = 1
selft = 5
self.textBox.insert(END, "READY")
self.textBox.configure(font=('arial narrow', 17, 'normal'), bg="green", fg="white")
self.botshoot.configure(state=NORMAL)
self.botStop.configure(state=DISABLED)
self.botQuit.configure(state=NORMAL)
remainshots = shootnumber
intervalometer(root)
root.mainloop()

I don't see how this is even an issue since the start method should lock up the entire program, including the input from the button. If the button detection is in it's own thread or something, you could just add a check. The easiest thing to check is the tk Button state:
def start(self, *args, **kwargs):
if self.botshoot['state'] == DISABLED:
print 'already running'
return # abort this method
self.botshoot.configure(state=DISABLED)
# etc ...

Related

Why do I get an Recursion error whenever i am deleting a letter from a modified stirng And how do I solve it?

I am trying to make a choice game where you can write and rewrite a name of the character in the game but whenever I try to delete a letter whilst testing the code I get an Recursion error
What is the cause to this problem and how to avoid it?
Here is my code
import pygame as pg
pg.init()
import time
win = pg.display.set_mode((900,600))
pg.display.set_caption("Choices")
go = 0
user_text = ''
lbrown = 225, 156, 0
brown = 192, 128, 0
dbrown = 128, 64, 0
black = 0, 0, 0
dgrey = 64, 64, 64
grey = 128,128,128
lgrey = 192,192,192
white = 255, 255, 255
red = 255, 0, 0
orange = 255,128,0
yellow = 255,223,0
lgreen = 128,255,0
green = 0,255,0
dgreen = 0,128,0
turcoise = 0,192,128
lblue = 0,128,255
blue = 0,0,255
dblue = 0,0,128
blurple = 128,0,192
purple = 192,0,192
pirple = 167, 0, 167
rpink = 255,0,128
pink = 255,0,255
startclick = 0
class BG(pg.sprite.Sprite):
def __init__(self):
pg.sprite.Sprite.__init__(self)
self.image = pg.Surface([400,100])
self.image.fill(white)
self.rect = self.image.get_rect()
class START(pg.sprite.Sprite):
def __init__(self):
pg.sprite.Sprite.__init__(self)
self.image = pg.Surface([200,100])
self.image.fill(green)
self.rect = self.image.get_rect()
class START_TEXT(pg.sprite.Sprite):
def __init__(self):
pg.sprite.Sprite.__init__(self)
font = pg.font.SysFont('Comic Sans MS', 40)
self.image = font.render('Start',False, pink)
self.rect = self.image.get_rect()
bg = BG()
bg.rect.x = 25
bg.rect.y = 100
start = START()
start.rect.x = 450
start.rect.y = 260
start_txt = START_TEXT()
start_txt.rect.x = 495
start_txt.rect.y = 280
all_sprite = pg.sprite.Group()
all_sprite.add(start,start_txt)
win.fill(purple)
def redraw():
all_sprite.draw(win)
pg.display.update()
run = True
while run:
pos = pg.mouse.get_pos()
print(startclick)
for event in pg.event.get():
if event.type == pg.QUIT:
run = False
if start.rect.collidepoint(pos):
start.image.fill(dgreen)
if event.type == pg.MOUSEBUTTONDOWN:
startclick = 1
win.fill(black)
all_sprite.remove(start,start_txt)
else:
start.image.fill(green)
key = pg.key.get_pressed()
if key[pg.K_BACKSPACE]:
all_sprite.remove(bg, user_text)
user_text = user_text[:-1]
go = 1
else:
if event.type == pg.KEYDOWN:
user_text += event.unicode
usertex = user_text
class User_TxT(pg.sprite.Sprite):
def __init__(self):
pg.sprite.Sprite.__init__(self)
font = pg.font.SysFont('Comic Sans MS', 40)
self.image = font.render(usertex, True, pink)
self.rect = self.image.get_rect()
user_txt = User_TxT()
user_txt.rect.x = 70
user_txt.rect.y = 120
if startclick == 1:
all_sprite.add(bg, user_txt)
pg.display.flip()
redraw()
quit()
pg.quit()
And the Recursion Error
packages\pygame\sprite.py", line 471, in
if isinstance(sprite, Sprite):
RecursionError: maximum recursion depth exceeded while calling a Python object
Why is this happening?
I've modified your User_TxT sprite class to support an update function to change its text. This will prevent the need to remove and recreate the sprite which causes your recursion error.
import pygame as pg
pg.init()
import time
win = pg.display.set_mode((900,600))
pg.display.set_caption("Choices")
go = 0
user_text = ''
lbrown = 225, 156, 0
brown = 192, 128, 0
dbrown = 128, 64, 0
black = 0, 0, 0
dgrey = 64, 64, 64
grey = 128,128,128
lgrey = 192,192,192
white = 255, 255, 255
red = 255, 0, 0
orange = 255,128,0
yellow = 255,223,0
lgreen = 128,255,0
green = 0,255,0
dgreen = 0,128,0
turcoise = 0,192,128
lblue = 0,128,255
blue = 0,0,255
dblue = 0,0,128
blurple = 128,0,192
purple = 192,0,192
pirple = 167, 0, 167
rpink = 255,0,128
pink = 255,0,255
startclick = 0
class BG(pg.sprite.Sprite):
def __init__(self):
pg.sprite.Sprite.__init__(self)
self.image = pg.Surface([400,100])
self.image.fill(white)
self.rect = self.image.get_rect()
class START(pg.sprite.Sprite):
def __init__(self):
pg.sprite.Sprite.__init__(self)
self.image = pg.Surface([200,100])
self.image.fill(green)
self.rect = self.image.get_rect()
class START_TEXT(pg.sprite.Sprite):
def __init__(self):
pg.sprite.Sprite.__init__(self)
font = pg.font.SysFont('Comic Sans MS', 40)
self.image = font.render('Start',False, pink)
self.rect = self.image.get_rect()
class User_TxT(pg.sprite.Sprite):
def __init__(self, usertex):
pg.sprite.Sprite.__init__(self)
self.update(usertex)
def update(self, usertex):
font = pg.font.SysFont('Comic Sans MS', 40)
self.image = font.render(usertex, True, pink)
self.rect = self.image.get_rect()
bg = BG()
bg.rect.x = 25
bg.rect.y = 100
start = START()
start.rect.x = 450
start.rect.y = 260
start_txt = START_TEXT()
start_txt.rect.x = 495
start_txt.rect.y = 280
user_txt = User_TxT(user_text)
all_sprite = pg.sprite.Group()
all_sprite.add(start,start_txt)
win.fill(purple)
def redraw():
all_sprite.draw(win)
pg.display.update()
run = True
while run:
pos = pg.mouse.get_pos()
print(startclick)
for event in pg.event.get():
if event.type == pg.QUIT:
run = False
if start.rect.collidepoint(pos):
start.image.fill(dgreen)
if event.type == pg.MOUSEBUTTONDOWN:
startclick = 1
win.fill(black)
all_sprite.remove(start,start_txt)
else:
start.image.fill(green)
key = pg.key.get_pressed()
if key[pg.K_BACKSPACE]:
# all_sprite.remove(bg, user_text)
user_text = user_text[:-1]
go = 1
else:
if event.type == pg.KEYDOWN:
user_text += event.unicode
# usertex = user_text
user_txt.update(user_text)
user_txt.rect.x = 70
user_txt.rect.y = 120
if startclick == 1:
all_sprite.add(bg, user_txt)
startclick = 0
pg.display.flip()
redraw()
quit()
pg.quit()
I've tried to make minimal changes to your code to avoid confusion.
EDIT to add some additional explanation:
I changed the User_TxT sprite class to take an input string as its initial text string to display and to also have an update() function so that its text string can be changed. This function is also what we need to do when initialising the sprite, so to prevent duplication, it's called from __init__(). That way you only need to have one sprite. You were also redefining and instantiating the User_TxT class for every event, which is unnecessary.
To help identify the code differences, you can use a diff tool, like WinMerge on Windows, or the command line diff tool on Linux.
If you run into further issues with your code, you should ask a new question, if you create a Minimal, Reproducible Example it will make it easier to help you.

add different widgets to each wxnotebook tab permanently in a txt file or sqlite

Please how can I add permanently different widgets in the tabs and save them permanently
<html>
<pre>
import wx
tabs = []
with open('test.txt','r') as file:
for element in file.readlines():
tabs.append(element)
class TabPanel(wx.Panel):
def __init__(self, parent, pageNum):
self.parent = parent
self.pageNum = pageNum
wx.Panel.__init__(self, parent=parent)
class DemoFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, wx.ID_ANY, "Notebook", size=(600,400))
panel = wx.Panel(self)
self.tab_num = len(tabs)
self.notebook = wx.Notebook(panel)
for tab in tabs:
name = "Page " + str(tab)
tab = TabPanel(self.notebook, 1)
self.notebook.AddPage(tab, name)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(self.notebook, 1, wx.ALL|wx.EXPAND, 5)
btn = wx.Button(panel, label="Add Page")
btn.Bind(wx.EVT_BUTTON, self.addPage)
sizer.Add(btn)
panel.SetSizer(sizer)
self.Layout()
self.Show()
def addPage(self, event):
self.tab_num += 1
new_tab = TabPanel(self.notebook, self.tab_num)
self.notebook.AddPage(new_tab, "Page %s" % self.tab_num)
tabs.append(self.tab_num)
print()
with open('test.txt','a+') as file:
file.write(str(self.tab_num))
file.write('\n')
if __name__ == "__main__":
app = wx.App(False)
frame = DemoFrame()
app.MainLoop()
</pre>
</html>
Something like this should get you started (sorry not readdly familiar with python):
class DemoFrame(wx.Frame):
def __init__(self):
self.tab_num = 1
wx.Frame.__init__(self, None, wx.ID_ANY, "Notebook", size=(600,400))
panel = wx.Panel(self)
with open( "test.txt", "r" as file:
self.tab_num = file.read()
self.notebook = wx.Notebook(panel)
for tab in [1..self.tab_num]:
name = "Page " + str(tab)
tab = TabPanel(self.notebook, 1)
self.notebook.AddPage(tab, name)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(self.notebook, 1, wx.ALL|wx.EXPAND, 5)
btn = wx.Button(panel, label="Add Page")
btn.Bind(wx.EVT_BUTTON, self.addPage)
sizer.Add(btn)
panel.SetSizer(sizer)
self.Layout()
self.Show()
def addPage(self, event):
self.tab_num += 1
new_tab = TabPanel(self.notebook, self.tab_num)
self.notebook.AddPage(new_tab, "Page %s" % self.tab_num)
tabs.append(self.tab_num)
print()
with open('test.txt','a+') as file:
file.write(str(self.tab_num))
file.write('\n')
if __name__ == "__main__":
app = wx.App(False)
frame = DemoFrame()
app.MainLoop()

Maximum value of QSlider?

What is the maximum value of QSlider, in the datasheet, it is just mentioned as int.
I tried with "1000000". but the Slider starts bugging.
QSlider.setMaximum(1000000);
Image with the bug, the blue color and the cursor don't move well at same speed, if the number is at max : 999999999, the cursor don't move at all.
when I put : max at : 650000 that works very well. That is perhaps an OS problem, I am using IOS..
By the way, here is an update of code, works fine with 100000 x 2 possible values:
from PyQt5 import QtCore, QtGui, QtWidgets
import sys
MAXVAL = 650000
class RangeSliderClass(QtWidgets.QWidget):
def __init__(self):
super().__init__()
self.minTime = 0
self.maxTime = 0
self.minRangeTime = 0
self.maxRangeTime = 0
self.middleTime = self.getMiddleTime()
self.halfTimeInterval = self.middleTime - self.minTime
self.sliderMin = MAXVAL
self.sliderMax = MAXVAL
self.setupUi(self)
def setupUi(self, RangeSlider):
RangeSlider.setObjectName("RangeSlider")
RangeSlider.resize(631, 65)
RangeSlider.setMaximumSize(QtCore.QSize(16777215, 65))
self.RangeBarVLayout = QtWidgets.QVBoxLayout(RangeSlider)
self.RangeBarVLayout.setContentsMargins(5, 0, 5, 0)
self.RangeBarVLayout.setSpacing(0)
self.RangeBarVLayout.setObjectName("RangeBarVLayout")
self.datesFrame = QtWidgets.QFrame(RangeSlider)
self.datesFrame.setMaximumSize(QtCore.QSize(16777215, 28))
self.datesFrame.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.datesFrame.setFrameShadow(QtWidgets.QFrame.Raised)
self.datesFrame.setObjectName("datesFrame")
self.datesHLayout = QtWidgets.QHBoxLayout(self.datesFrame)
self.datesHLayout.setContentsMargins(5, 2, 5, 2)
self.datesHLayout.setObjectName("datesHLayout")
## startTime Calendar Widget
self.startTime = QtWidgets.QDateTimeEdit(self.datesFrame)
self.startTime.setMinimumSize(QtCore.QSize(183, 0))
self.startTime.setMaximumSize(QtCore.QSize(185, 24))
self.startTime.setDate(QtCore.QDate.currentDate().addDays(-1))
self.startTime.setMaximumDateTime(QtCore.QDateTime(QtCore.QDate(2999, 12, 31), QtCore.QTime(23, 59, 59)))
self.startTime.setMaximumDate(QtCore.QDate(2999, 12, 31))
self.startTime.setMinimumDate(QtCore.QDate(2000, 1, 1))
self.startTime.setCalendarPopup(True)
self.startTime.setObjectName("startTime")
self.startTime.dateChanged.connect(self.startDateChangeHandler)
self.datesHLayout.addWidget(self.startTime)
spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.datesHLayout.addItem(spacerItem)
## entTime Calendar Widget
self.endTime = QtWidgets.QDateTimeEdit(self.datesFrame)
self.endTime.setMinimumSize(QtCore.QSize(183, 0))
self.endTime.setMaximumSize(QtCore.QSize(185, 24))
self.endTime.setDate(QtCore.QDate.currentDate())
self.endTime.setMaximumDate(QtCore.QDate(2999, 12, 31))
self.endTime.setMinimumDate(QtCore.QDate(2000, 1, 1))
self.endTime.setCalendarPopup(True)
self.endTime.setObjectName("endTime")
self.endTime.dateChanged.connect(self.endDateChangeHandler)
self.datesHLayout.addWidget(self.endTime)
## Init Time
self.minTime = self.startTime.dateTime().toTime_t()
self.maxTime = self.endTime.dateTime().toTime_t()
self.minRangeTime = self.minTime
self.maxRangeTime = self.maxTime
self.middleTime = self.getMiddleTime()
self.halfTimeInterval = self.middleTime - self.minTime
self.RangeBarVLayout.addWidget(self.datesFrame)
self.slidersFrame = QtWidgets.QFrame(RangeSlider)
self.slidersFrame.setMaximumSize(QtCore.QSize(16777215, 25))
self.slidersFrame.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.slidersFrame.setFrameShadow(QtWidgets.QFrame.Raised)
self.slidersFrame.setObjectName("slidersFrame")
self.horizontalLayout = QtWidgets.QHBoxLayout(self.slidersFrame)
self.horizontalLayout.setSizeConstraint(QtWidgets.QLayout.SetMinimumSize)
self.horizontalLayout.setContentsMargins(5, 2, 5, 2)
self.horizontalLayout.setSpacing(0)
self.horizontalLayout.setObjectName("horizontalLayout")
## Start Slider Widget
self.startSlider = QtWidgets.QSlider(self.slidersFrame)
self.startSlider.setMaximum(self.sliderMin)
self.startSlider.setMinimumSize(QtCore.QSize(100, 5))
self.startSlider.setMaximumSize(QtCore.QSize(16777215, 10))
font = QtGui.QFont()
font.setKerning(True)
self.startSlider.setFont(font)
self.startSlider.setAcceptDrops(False)
self.startSlider.setAutoFillBackground(False)
self.startSlider.setOrientation(QtCore.Qt.Horizontal)
self.startSlider.setInvertedAppearance(True)
self.startSlider.setObjectName("startSlider")
self.startSlider.setValue(MAXVAL)
self.startSlider.sliderReleased.connect(self.startSliderHandler)
self.horizontalLayout.addWidget(self.startSlider)
## End Slider Widget
self.endSlider = QtWidgets.QSlider(self.slidersFrame)
self.endSlider.setMaximum(MAXVAL)
self.endSlider.setMinimumSize(QtCore.QSize(100, 5))
self.endSlider.setMaximumSize(QtCore.QSize(16777215, 10))
self.endSlider.setTracking(True)
self.endSlider.setOrientation(QtCore.Qt.Horizontal)
self.endSlider.setObjectName("endSlider")
self.endSlider.setValue(self.sliderMax)
self.endSlider.sliderReleased.connect(self.endSliderHandler)
self.horizontalLayout.addWidget(self.endSlider)
self.RangeBarVLayout.addWidget(self.slidersFrame)
self.retranslateUi(RangeSlider)
QtCore.QMetaObject.connectSlotsByName(RangeSlider)
self.show()
def getMiddleTime(self, maxTime = None, minTime = None):
if minTime == None :
minTime = self.minRangeTime
if maxTime == None :
maxTime = self.maxRangeTime
return (minTime + maxTime)/2
def getRangeTime(self):
return self.minRangeTime, self.maxRangeTime
def startSliderHandler(self):
self.sliderMin = self.startSlider.value()
self.minRangeTime = int(self.middleTime - self.halfTimeInterval * self.sliderMin / MAXVAL)
#print("\n\nNew Min Time Range : ", self.minRangeTime, " Min : ", self.minTime, "Minddle : ", self.middleTime)
def endSliderHandler(self):
self.sliderMax = self.endSlider.value()
self.maxRangeTime = int(self.middleTime + self.halfTimeInterval * self.sliderMax / MAXVAL)
print("\n\nNew Min Time Range : ", self.maxRangeTime, " Max : ", self.maxTime, "Minddle : ", self.middleTime)
def startDateChangeHandler(self):
self.minTime = self.startTime.dateTime().toTime_t()
#print("MinTime range : ", self.minTime)
def endDateChangeHandler(self):
self.maxTime = self.endTime.dateTime().toTime_t()
#print("MaxTime range : ", self.maxTime)
def retranslateUi(self, RangeSlider):
_translate = QtCore.QCoreApplication.translate
RangeSlider.setWindowTitle(_translate("RangeSlider", "Time interval"))
self.startTime.setDisplayFormat(_translate("RangeSlider", "dd/MM/yyyy HH:mm:ss .zz"))
self.endTime.setDisplayFormat(_translate("RangeSlider", "dd/MM/yyyy HH:mm:ss .zz"))
app = QtWidgets.QApplication(sys.argv)
awindow = RangeSliderClass()
sys.exit(app.exec_())
You can set QSlider maximum value with 9 digits.
QSlider.setMaximum(999999999);
The answer of #aghilpro is not incorrect on Qt Designer the limit is 999999999 (9 digits)
But QSlider inherits QAbstractSlider and on definition of properties we have:
...
Q_PROPERTY(int minimum READ minimum WRITE setMinimum)
Q_PROPERTY(int maximum READ maximum WRITE setMaximum)
...
Then the max int value is 2,147,483,647 (10 digits) then 9999999999 overflow that value;

Only one button in a panel with multiple togglebuttons changes color - wxPython

I want to set the color of a toggle button of my choice in the panel that I have created. The problem is that in the numerous toggle buttons that I have displayed on my panel when I want to change the color of each one only the color of the last button changes. Here's my code:
import wx
class Frame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self,None)
self.panel = wx.Panel(self,wx.ID_ANY)
self.sizer = wx.BoxSizer(wx.VERTICAL)
self.flags_panel = wx.Panel(self, wx.ID_ANY, style = wx.SUNKEN_BORDER)
self.sizer.Add(self.flags_panel)
self.SetSizer(self.sizer,wx.EXPAND | wx.ALL)
self.flags = Flags(self.flags_panel, [8,12])
self.flags.Show()
class Flags (wx.Panel):
def __init__(self,panel, num_flags = []):#,rows = 0,columns = 0,radius = 0, hspace = 0, vspace = 0,x_start = 0, y_start = 0
wx.Panel.__init__(self,panel,-1, size = (350,700))
num_rows = num_flags[0]
num_columns = num_flags[1]
x_pos_start = 10
y_pos_start = 10
i = x_pos_start
j = y_pos_start
buttons = []
for i in range (num_columns):
buttons.append('toggle button')
self.ButtonValue = False
for button in buttons:
index = 0
while index != 15:
self.Button = wx.ToggleButton(self,-1,size = (10,10), pos = (i,j))
self.Bind(wx.EVT_TOGGLEBUTTON,self.OnFlagCreation, self.Button)
self.Button.Show()
i += 15
index += 1
j += 15
i = 10
self.Show()
def OnFlagCreation(self,event):
if not self.ButtonValue:
self.Button.SetBackgroundColour('#fe1919')
self.ButtonValue = True
else:
self.Button.SetBackgroundColour('#14e807')
self.ButtonValue = False
if __name__ == '__main__':
app = wx.App(False)
frame = Frame()
frame.Show()
app.MainLoop()
Your problem is quite simple. The last button is always changed because it's the last button defined:
self.Button = wx.ToggleButton(self,-1,size = (10,10), pos = (i,j))
Each time through the for loop, you reassign the self.Button attribute to a different button. What you want to do is extract the button from your event object and change its background color. So change your function to look like this:
def OnFlagCreation(self,event):
btn = event.GetEventObject()
if not self.ButtonValue:
btn.SetBackgroundColour('#fe1919')
self.ButtonValue = True
else:
btn.SetBackgroundColour('#14e807')
self.ButtonValue = False
See also:
http://www.blog.pythonlibrary.org/2011/09/20/wxpython-binding-multiple-widgets-to-the-same-handler/

Update canvas without delete the existing objects

I have a QCanvas with multiple objects on it. How could I update the canvas and put new object onto it without delete the existing ones?
I want the canvas to draw every existing objects, even if I draw a new one. A new object is generated on every mouse event.
class CANVAS(QtGui.QWidget):
def __init__(self , parent):
super(CANVAS , self).__init__(parent)
self.setGeometry( 0 , 30 , 530 , 530 )
self.frame = QtGui.QFrame(self)
self.CLICKED = 1
self.FUNCTION = 0
self.x =""
self.y =""
def paintEvent(self, e):
qp = QtGui.QPainter()
qp.begin(self)
self.drawPoints(qp)
qp.end()
def drawPoints(self, qp):
qp.setPen(QtCore.Qt.red)
t = points.point()
print self.x
if self.CLICKED == 1:
qp.drawRect(int(self.x), int(self.y), 10, 10)
self.CLICKED = 0
if self.FUNCTION == 1:
for k in range(0,360,1):
radius = 50
a = float(self.x) + radius * np.cos(k)
b = float(self.y) + radius * np.sin(k)
qp.drawPoint(a,b)
qp.drawPoint(int(self.x), int(self.y))
print "circle done"
self.FUNCTION = 0
elif self.FUNCTION == 2:
start_P = points.point(int(self.x), int(self.y))
a = 15
b = 20
upperL = points.point((int(self.x) + (10 * a)), int(self.y))
P = [start_P, upperL]
dummy1 = LinInt(P, qp)
leftL = points.point((int(self.x)), ((int(self.y))+(10*b)))
P = [start_P, leftL]
dummy2 = LinInt(P, qp)
tmp = dummy1.pop()
rightL = points.point((tmp.getX()),((int(self.y))+(10*b)))
P = [tmp, rightL]
LinInt(P, qp)
P = [leftL, rightL]
LinInt(P, qp)
self.FUNCTION = 0
print "rectangle done"
elif self.FUNCTION == 3:
print "curve"
def mousePressEvent(self, event):
self.x = ""
self.y = ""
coordinates = event.x()
for i in str(coordinates):
if i.isdigit():
self.x+=i
coordinates = event.y()
for i in str(coordinates):
if i.isdigit():
self.y+=i
self.CLICKED = 1
self.update()
In the constructor, create an empty list. In your drawPoints, do:
if self.CLICKED == 1:
rect = QRect(int(self.x), int(self.y), 10, 10)
self.rects.append(rect)
qp.drawRects(self.rects)

Resources