tkinter: changing button attributes for buttons created in loop - button

Right now this would work, but I would prefer to do it with for loops and a list.
I've tried, but I cannot figure out how to get the name of the buttons that were created in the for loop.
import tkinter as tk
def toggle(button):
#----------------------------
# Manages the button toggling
#----------------------------
if button == 0:
if button0.config('relief')[-1] == 'sunken':
button0.config(relief='raised')
else:
button0.config(relief='sunken')
if button == 1:
if button1.config('relief')[-1] == 'sunken':
button1.config(relief='raised')
else:
button1.config(relief='sunken')
if button == 2:
if button2.config('relief')[-1] == 'sunken':
button2.config(relief='raised')
else:
button2.config(relief='sunken')
if button == 3:
if button3.config('relief')[-1] == 'sunken':
button3.config(relief='raised')
else:
button3.config(relief='sunken')
if button == 4:
if button4.config('relief')[-1] == 'sunken':
button4.config(relief='raised')
else:
button4.config(relief='sunken')
if button == 5:
if button5.config('relief')[-1] == 'sunken':
button5.config(relief='raised')
else:
button5.config(relief='sunken')
if button == 6:
if button6.config('relief')[-1] == 'sunken':
button6.config(relief='raised')
else:
button6.config(relief='sunken')
if button == 7:
if button7.config('relief')[-1] == 'sunken':
button7.config(relief='raised')
else:
button7.config(relief='sunken')
if button == 8:
if button8.config('relief')[-1] == 'sunken':
button8.config(relief='raised')
else:
button8.config(relief='sunken')
if button == 9:
if button9.config('relief')[-1] == 'sunken':
button9.config(relief='raised')
else:
button9.config(relief='sunken')
if button == 10:
if button10.config('relief')[-1] == 'sunken':
button10.config(relief='raised')
else:
button10.config(relief='sunken')
if button == 11:
if button11.config('relief')[-1] == 'sunken':
button11.config(relief='raised')
else:
button11.config(relief='sunken')
if button == 12:
if button12.config('relief')[-1] == 'sunken':
button12.config(relief='raised')
else:
button12.config(relief='sunken')
if button == 13:
if button13.config('relief')[-1] == 'sunken':
button13.config(relief='raised')
else:
button13.config(relief='sunken')
if button == 14:
if button14.config('relief')[-1] == 'sunken':
button14.config(relief='raised')
else:
button14.config(relief='sunken')
root = tk.Tk()
root.title("Chamber Calibration")
#------------------------------------------
# Sets up the different temperature buttons
#------------------------------------------
button0 = tk.Button(root, text="-65C", width = 25, relief='raised', command=lambda: toggle(0))
button0.grid(row = 0, column = 3)
button1 = tk.Button(root, text="-40C", width = 25, relief='raised', command=lambda: toggle(1))
button1.grid(row = 1, column = 3)
button2 = tk.Button(root, text="-20C", width = 25, relief='raised', command=lambda: toggle(2))
button2.grid(row = 2, column = 3)
button3 = tk.Button(root, text="0C", width = 25, relief='raised', command=lambda: toggle(3))
button3.grid(row = 3, column = 3)
button4 = tk.Button(root, text="23C", width = 25, relief='raised', command=lambda: toggle(4))
button4.grid(row = 4, column = 3)
button5 = tk.Button(root, text="30C", width = 25, relief='raised', command=lambda: toggle(5))
button5.grid(row = 5, column = 3)
button6 = tk.Button(root, text="45C", width = 25, relief='raised', command=lambda: toggle(6))
button6.grid(row = 6, column = 3)
button7 = tk.Button(root, text="65C", width = 25, relief='raised', command=lambda: toggle(7))
button7.grid(row = 7, column = 3)
button8 = tk.Button(root, text="90C", width = 25, relief='raised', command=lambda: toggle(8))
button8.grid(row = 8, column = 3)
button9 = tk.Button(root, text="130C", width = 25, relief='raised', command=lambda: toggle(9))
button9.grid(row = 9, column = 3)
button10 = tk.Button(root, text="165C", width = 25, relief='raised', command=lambda: toggle(10))
button10.grid(row = 10, column = 3)
button11 = tk.Button(root, text="38C 15%RH", width = 25, relief='raised', command=lambda: toggle(11))
button11.grid(row = 11, column = 3)
button12 = tk.Button(root, text="38C 95%RH", width = 25, relief='raised', command=lambda: toggle(12))
button12.grid(row = 12, column = 3)
button13 = tk.Button(root, text="50C 95%RH", width = 25, relief='raised', command=lambda: toggle(13))
button13.grid(row = 13, column = 3)
button14 = tk.Button(root, text="85C 95%RH", width = 25, relief='raised', command=lambda: toggle(14))
button14.grid(row = 14, column = 3)
#-----------
# Starts GUI
#-----------
root.mainloop()
What I've tried:
import tkinter as tk
def toggle(button):
if button == 0:
if button0.config('relief')[-1] == 'sunken':
button0.config(relief='raised')
else:
button0.config(relief='sunken')
root = tk.Tk()
root.title("Chamber Calibration")
#------------------------------------------
# Sets up the different temperature buttons
#------------------------------------------
STEPS = ['-65C', '-40C', '-20C', '0C', '23C', '30C', '45C', '65C', '90C', '130C', '165C',
'38C 15%RH', '38C 95%RH', '50C 95%RH', '85C 95%RH']
count = 0
for step in STEPS:
newname = ('button' + str(count))
print(newname)
newname = tk.Button(root, text=step, width = 25, relief='raised',
command=lambda button=count: toggle(button))
newname.grid(row = count, column = 3)
count += 1
#-----------
# Starts GUI
#-----------
root.mainloop()
Any pointers would be appreciated.

Don't try to create variable names, just store the buttons in a list:
buttons = []
for step in STEPS:
buttons.append(tk.Button(...))
...
...
buttons[i].configure(...)

Just as a side note, you were dead on Bryan, thank you.
This is the working code:
import tkinter as tk
def toggle(num):
if buttons[num].config('relief')[-1] == 'sunken':
buttons[num].config(relief='raised')
else:
buttons[num].config(relief='sunken')
root = tk.Tk()
root.title("Chamber Calibration")
#------------------------------------------
# Sets up the different temperature buttons
#------------------------------------------
STEPS = ['-65C', '-40C', '-20C', '0C', '23C', '30C', '45C', '65C', '90C', '130C', '165C',
'38C 15%RH', '38C 95%RH', '50C 95%RH', '85C 95%RH']
buttons = []
count = 0
for step in STEPS:
buttons.append(tk.Button(root, text=step, width = 25, relief='raised',
command=lambda num=count: toggle(num)))
buttons[count].grid(row = count, column = 3)
count += 1
#-----------
# Starts GUI
#-----------
root.mainloop()

Related

Why do I get error "missing 1 required positional argument"?

Why I continue getting the error :
missing 1 required positional argument: 'category_id'
when the argument is already passed within query function in Backend class? I also don't understand the error of unfilled self or missing positional argument self:
missing 1 required positional argument: 'self'
I tried passing self to display_account_types() in Frontend class but it doesn't reflect. Do I need to pass self within the inner nested functions within a class?
import tkinter
from tkinter import *
from tkinter import ttk
import tkinter.messagebox
import sqlite3
root =Tk()
root.title('Simple Application')
root.config(bg='SlateGrey')
root.geometry("")
# BackEnd
class Backend():
def __init__(self):
self.conn = sqlite3.connect('accounting.db')
self.cur = self.conn.cursor()
self.conn.execute("""CREATE TABLE IF NOT EXISTS account_type(
id INTEGER PRIMARY KEY,
category_type INTEGER NOT NULL,
category_id TEXT NOT NULL
)"""),
self.conn.commit()
self.conn.close()
def insert_account_type(self, category_type, category_id):
self.conn = sqlite3.connect('accounting.db')
self.cur = self.conn.cursor()
self.cur.execute("""INSERT INTO account_type(category_id, category_type) VALUES(?,?);""",
(self,category_type, category_id,))
self.conn.commit()
self.conn.close()
def view_account_type(self):
self.conn = sqlite3.connect('accounting.db')
self.cur = self.conn.cursor()
self.cur.execute("SELECT * FROM account_type")
self.rows = self.cur.fetchall()
self.conn.close()
return self.rows
# calling the class
tb = Backend()
# Front End
class Frontend():
def __init__(self, master):
# Frames
self.top_frame = LabelFrame(master,bg ='SlateGrey', relief=SUNKEN)
self.top_frame.pack()
self.bottom_frame = LabelFrame(master, bg = 'SlateGrey', relief=SUNKEN)
self.bottom_frame.pack()
self.right_frame = LabelFrame(self.top_frame, bg = 'SlateGrey', relief = FLAT,
text = 'Details Entry',fg = 'maroon')
self.right_frame.pack(side = RIGHT, anchor = NE)
self.side_frame = LabelFrame(self.top_frame,bg ='SlateGrey',relief=SUNKEN,text = 'Menu Buttons',fg = 'maroon')
self.side_frame.pack(side = LEFT,anchor = NW)
self.bot_frame = LabelFrame(self.bottom_frame, bg='Grey',relief = SUNKEN,text = 'Field View',fg = 'maroon')
self.bot_frame.pack(side = BOTTOM,anchor = SW)
# Side Buttons
self.btn1 = Button(self.side_frame,
text='Main Account Types',
bg='SteelBlue4',
font=('cambria', 11),
anchor=W,
fg='white',
width=18,height=2,
command=lambda :[self.main_account()])
self.btn1.grid(row=0, column=0, pady=0, sticky=W)
def main_account(self):
# variables
self.category_type = StringVar()
self.category_id = StringVar()
# functions
def add_main_accounts():
if self.category_type.get() == "" or self.category_id.get() == "":
tkinter.messagebox.showinfo('All fields are required')
else:
Backend.insert_account_type(
self.category_type.get(),
self.category_id.get(),) # category type unfilled
tkinter.messagebox.showinfo('Entry successful')
def display_account_types(self):
self.trv.delete(*self.trv.get_children())
for self.rows in Backend.view_account_type(self):
self.trv.insert("", END, values=self.rows)
def get_account_type(e):
self.selected_row = self.trv.focus()
self.data = self.trv.item(self.selected_row)
global row
row = self.data["values"]
"""Grab items and send them to entry fields"""
self.category_id.set(row[1])
self.category_type.set(row[2])
"""=================TreeView==============="""
# Scrollbars
ttk.Style().configure("Treeview", background = "SlateGrey", foreground = "white", fieldbackground = "grey")
scroll_x = Scrollbar(self.bot_frame, orient = HORIZONTAL)
scroll_x.pack(side = BOTTOM, fill = X)
scroll_y = Scrollbar(self.bot_frame, orient = VERTICAL)
scroll_y.pack(side = RIGHT, fill = Y)
# Treeview columns & setting scrollbars
self.trv = ttk.Treeview(self.bot_frame, height=3, columns=
('id', 'category_id', 'category_type'), xscrollcommand = scroll_x.set, yscrollcommand = scroll_y.set)
# Treeview style configuration
ttk.Style().configure("Treeview", background = "SlateGrey", foreground = "white", fieldbackground = "grey")
# Configure vertical and Horizontal scroll
scroll_x.config(command = self.trv.xview)
scroll_y.config(command = self.trv.yview)
# Treeview Headings/columns
self.trv.heading('id', text = "No.")
self.trv.heading('category_id', text = 'Category ID')
self.trv.heading('category_type', text = 'Category Type')
self.trv['show'] = 'headings'
# Treeview columns width
self.trv.column('id', width = 23)
self.trv.column('category_id', width = 70)
self.trv.column('category_type', width = 100)
self.trv.pack(fill = BOTH, expand = YES)
# Binding Treeview with data
self.trv.bind('<ButtonRelease-1>',get_account_type)
# Account Types Labels
self.lbl1 = Label(self.right_frame,text = 'Category ID',anchor = W,
width=10,font = ('cambria',11,),bg = 'SlateGrey')
self.lbl1.grid(row = 0,column = 0,pady = 5)
self.lbl2 = Label(self.right_frame, text = 'Category Type', anchor = W,
width = 10,font = ('cambria',11,),bg = 'SlateGrey')
self.lbl2.grid(row = 1, column = 0,pady = 5,padx=5)
self.blank_label = Label(self.right_frame, bg='SlateGrey')
self.blank_label.grid(row=2, columnspan=2, pady=10)
# Account Type Entries
self.entry1 = Entry(self.right_frame,textvariable = self.category_id,
font = ('cambria',11,),bg = 'Grey',width=14)
self.entry1.grid(row = 0,column=1,sticky = W,padx = 5)
self.entry2 = Entry(self.right_frame, textvariable = self.category_type,
font = ('cambria', 11,), bg = 'Grey',width = 14)
self.entry2.grid(row = 1, column = 1, sticky = W,pady = 5,padx = 5)
# Buttons
self.btn_1 = Button(self.right_frame,text = 'Add',font = ('cambria',12,'bold'),bg = 'SlateGrey',
activebackground='green', fg = 'white',width=12,height = 2,relief=RIDGE,
command = lambda :[add_main_accounts()])
self.btn_1.grid(row = 3,column = 0,pady = 15)
self.btn_2 = Button(self.right_frame, text = 'View', font = ('cambria', 12, 'bold'),
bg = 'SlateGrey',command=lambda :[display_account_types()],
activebackground='green', fg ='white', width=12, height = 2, relief = RIDGE)
self.btn_2.grid(row = 3, column = 1)
# calling the class
app = Frontend(root)
root.mainloop()
I got and answer to this question,
I just passed in the 'self' argument to the inner nested functions of the class as below and it worked.
# functions
def add_main_accounts(self):
if self.category_id.get() == "" or self.category_type.get() == "":
tkinter.messagebox.showinfo('All fields are required')
else:
Backend.insert_account_type(self,
self.category_id.get(),
self.category_type.get()) # category type unfilled
tkinter.messagebox.showinfo('Entry successful')
def display_account_types(self):
self.trv.delete(*self.trv.get_children())
for rows in Backend.view_account_type(self):
self.trv.insert("", END, values = rows)
return
def get_account_type(e):
self.selected_row = self.trv.focus()
self.data = self.trv.item(self.selected_row)
global row
self.row = self.data["values"]
"""Grab items and send them to entry fields"""
self.category_id.set(row[1])
self.category_type.set(row[2])
I think you should remove the self in display_account_types function like you did to the previous one.

Azerothcore, Change orb of deception from changing model to changing race

Trying to alter the item orb of deception. Currently when the item spell is cast, it changes the player to a predetermend modelID, instead, i want it to change your race so your gear looks the same.
There is a setRace() but i cannot get it to correctly change the race.
This is the original code
target->SetDisplayId(target->getGender() == GENDER_MALE ? 10135 : 10134);
Trying to change it to something like this that works
//if (target->getGender() == GENDER_MALE) { target->setRace(RACE_GNOME); }
//if (target->getGender() == GENDER_FEMALE) { target->setRace(RACE_GNOME); }
//target->setRace(target->getGender() == GENDER_MALE ? RACE_GNOME : RACE_GNOME);
//target->setRace(7);
target->setRace(RACE_GNOME);
None of these attemps work
void setRace(uint8 race);
{
RACE_NONE = 0,
RACE_HUMAN = 1,
RACE_ORC = 2,
RACE_DWARF = 3,
RACE_NIGHTELF = 4,
RACE_UNDEAD_PLAYER = 5,
RACE_TAUREN = 6,
RACE_GNOME = 7,
RACE_TROLL = 8,
//RACE_GOBLIN = 9,
RACE_BLOODELF = 10,
RACE_DRAENEI = 11
//RACE_FEL_ORC = 12,
//RACE_NAGA = 13,
//RACE_BROKEN = 14,
//RACE_SKELETON = 15,
//RACE_VRYKUL = 16,
//RACE_TUSKARR = 17,
//RACE_FOREST_TROLL = 18,
//RACE_TAUNKA = 19,
//RACE_NORTHREND_SKELETON = 20,
//RACE_ICE_TROLL = 21
};```

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