How do I set the color of a toggle button in wxpython? - button

I have a collection of button that I've created and need to change the color of the button when it's pressed. Currently it set the default colors (grey = inactive; light blue = active):
but I want to change the color of active to red.
Here's my button class:
class ButtonClass(wx.Panel):
def __init__(self, parent, name, id):
wx.Panel.__init__(self, parent)
self.name = name
self.taskid = id
self.button = wx.ToggleButton(self, 1, size=(50, 50))
self.button.SetLabel('Start')
self.mainSizer = wx.BoxSizer(wx.HORIZONTAL)
self.mainSizer.Add(self.button)
self.Bind(wx.EVT_TOGGLEBUTTON, self.toggledbutton, self.button)
# Where the buttons change state
def toggledbutton(self, event):
# Active State
if self.button.GetValue() == True:
self.button.SetLabel('Stop')
# Inactive State
if self.button.GetValue() == False:
self.button.SetLabel('Start')
I've tried using self.button.SetColour , self.button.SetBackgroundColour , self.button.SetForegroundColour all of which were not successful. Is there a way to accomplish this within wxpython?

It seems to be platform dependant. This worked for me in Ubuntu, but not in Windows.
self.ToggleButtonObj = wx.ToggleButton(self, -1, 'ButtonLabel')
self.ToggleButtonObj.Bind(wx.EVT_TOGGLEBUTTON, self.OnToggleClick)
def OnToggleClick(self,event):
if self.ToggleButtonObj.GetValue():
self.ToggleButtonObj.SetBackgroundColour('#color1')
else:
self.ToggleButtonObj.SetBackgroundColour('#color2')
Workaround:
self.Button = wx.Button(self, -1, 'ButtonLabel')
self.Button.Bind(wx.EVT_BUTTON, self.OnToggleClick)
self.ButtonValue = False
def OnToggleClick(self,event):
if not self.ButtonValue():
self.Button.SetBackgroundColour('#color1')
self.ButtonValue = True
else:
self.Button.SetBackgroundColour('#color2')
self.ButtonValue = False

SetBackgroundColour() worked for me using colour in RGB mode (like (255,255,255)) in Windows 7 with python 2.7.3.

Related

Streamlit session state and button

Does anyone know how the code below could be changed so that the print only happens when the button “Run” is clicked? Now the print is performed every time “inp” is changed.
import streamlit as st
inp = st.number_input(“inp”, min_value=0, max_value=10, step=1, value=10)
if ‘click’ not in st.session_state:
st.session_state.click = False
def onClickFunction():
st.session_state.click = True
st.session_state.out = inp
runButton = st.button(“Run”,
on_click=onClickFunction())
if st.session_state.click:
st.write(“out”, st.session_state.out)
Solution: remove the “()” after the onClickFunction.

Tkinter create RadioButtons from dictionary issue

Here is my problem: I've made a tkinter program which calculate the cost of a creation my wife make. She sews accessories. So far my program is working pretty well. I search in a JSON file if this fabric already exist in some kind of catalogue.
When my catalogue have the same fabric name, I want to make a popup window with radiobutton. By checking the correct radiobutton I chose the correct fabric. So I've extracted the dictionary of same fabric names, when I type the fabric name entry and then click on enter, it sends the dictionnary to the popup window which creates radiobutton in a for loop.
The problem comes here, my radiobutton are correctly made but impossible to get there state nor which button is checked...
First, here's the dictionary :
{"Tissu 1": {"Type": "Tissu", "Matière": "coton", "Prix du coupon": "8",
"Laise du coupon (cm)": "150",
"Prix au mètre (€)": 8.0,
"Fournisseur": "lol"},
"Tissu 2": {"Type": "Tissu", "Matière": "molleton", "Prix du coupon": "10",
"Laise du coupon (cm)": "150",
"Prix au mètre (€)": 10.0,
"Fournisseur": "lol"},
"Tissu 3": {"Type": "Tissu", "Matière": "coton", "Prix du coupon": "12",
"Laise du coupon (cm)": "150",
"Prix au mètre (€)": 12.0,
"Fournisseur": "mol"}}
Here's my code:
First there is the main class:
class ProgramCalcul(tk.Tk):
def __init__(self, *args, **kwargs):
self.frames = {}
for F in (StartPage, CalculTissuPage, CalculMercPage):
frame = F(container, self)
self.frames[F] = frame
frame.grid(row = 0, column = 0, sticky = "nsew")
self.show_frameSP(StartPage)
def show_frameSP(self, cont):
frame = self.frames[cont]
frame.tkraise()
Then I have a class for each other calcul page
Here is the fabric calcul page (I've removed some entries and other widgets for legibility and because they work fine):
class CalculTissuPage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
tissuType = tk.StringVar()
TissuNameEntry = tk.Entry(self, textvariable = tissuType, width = 50)
TissuNameEntry.grid(row = 2, padx = 20, pady = 5, sticky = "ew")
def keyPress(arg):
checkCatalogueTissu(TissuNameEntry.get())
TissuNameEntry.bind('<Return>', keyPress)
def checkCatalogueTissu(txt):
tmpDict = {}
with open("catalogue tissu.json") as json_file:
data = json.load(json_file)
dictLen = len(data)
for i in range(1, dictLen+1):
if "Tissu {}".format(i) not in data:
pass
else:
if data["Tissu {}".format(i)]["Matière"] == txt:
tmpDict["Tissu {}".format(i)] = data["Tissu {}".format(i)]
popupRadio(tmpDict)
def setText(txtPrix, txtFournisseur, txtLaise, txtLong):
couponPrixEntry.delete(0,tk.END)
couponPrixEntry.insert(0,txtPrix)
fournisseurEntry.delete(0, tk.END)
fournisseurEntry.insert(0, txtFournisseur)
laiseDimEntry.delete(0, tk.END)
laiseDimEntry.insert(0, txtLaise)
longCouponEntry.delete(0,tk.END)
longCouponEntry.insert(0,txtLong)
And finally the function which create the popup in which appear the radiobuttons:
def popupRadio(tmpDict):
popup = tk.Toplevel()
popup.wm_title("!")
popupVar = tk.IntVar()
def checkState(popupVar):
print(popupVar.get())
for (key, val) in tmpDict.items():
tk.Radiobutton(popup, text = key, variable = popupVar, value = val, command = checkState(popupVar)).grid()
print(key, popupVar.get())
chk = ttk.Button(popup, text = "Select this", command = checkState(popupVar))
chk.grid()
popup.mainloop()
When I run it, the checkState() method seems to run automatically and then the chk button doesn't do anything... I can check the radiobuttons but nothing happens (even if I pass the command=chechState in the radiobutton settings. I want to get which button is checked to use this value in my setText() method further.
for the moment, here is the output the print() send in my console :
0
Tissu 1 0
0
Tissu 3 0
0
So here I am, it's been 2 days since I've tried evrything I found on the web but nothing...
A little help would be very appreciated
PS: sorry if my english is not perfect :)

Why does WTForms have unbound fields the first time the page is loaded?

I have the following form classes:
class FieldsRequiredForm(FlaskForm):
class Meta:
def render_field(self, field, render_kw):
render_kw.setdefault('required', True)
return super().render_field(field, render_kw)
class SingleStringFieldForm(FieldsRequiredForm):
def __init__(self, field_label=None, question_id=None,
submit_label='Submit'):
super().__init__()
SingleStringFieldForm.answer = StringField(field_label)
SingleStringFieldForm.question_id = HiddenField(default=question_id)
SingleStringFieldForm.submit = SubmitField(submit_label)
class SingleRadioFieldForm(FieldsRequiredForm):
def __init__(self, field_label=None, question_id=None,
submit_label='Submit', choices=None):
super().__init__()
SingleRadioFieldForm.answer = RadioField(field_label, choices=choices)
SingleRadioFieldForm.question_id = HiddenField(default=question_id)
SingleRadioFieldForm.submit = SubmitField(submit_label)
The function that's using these forms looks like this:
#bp.route('/survey/<string:slug>', methods=['GET', 'POST'])
def question(slug):
survey = Survey.query.filter_by(slug=slug).first_or_404()
questions = survey.questions
question_ids = [question.id for question in questions]
if 'answers' not in session:
session['answers'] = json.dumps({id: None for id in question_ids})
answers = json.loads(session['answers'])
if request.method == 'POST':
record_submitted_answer()
answers = json.loads(session['answers'])
if None in answers.values():
question = get_next_question()
if question.category == 'word':
form = SingleStringFieldForm(field_label=question.question,
question_id=question.id)
elif question.category == 'likert':
form = SingleRadioFieldForm(field_label=question.question,
question_id=question.id,
choices=tuple(likert().items()))
else:
form = SingleStringFieldForm()
if form.validate_on_submit():
if None not in answers.values():
write_answers_to_database(survey=survey)
with open('app/static/ty.txt', 'r') as f:
ty = [x.strip() for x in f.readlines()]
return render_template('ty.html', ty=ty)
return redirect(url_for('survey.question', slug=slug))
return render_template('survey.html', form=form, answers=answers)
The first time I load the page after clearing the session, the form doesn't show up, and when I'm stepping through with a debugger when that happens, the debugger reports that form.answer has a value of:
<UnboundField(RadioField, ('Question 1',), {'choices': (('1', 'Strongly Agree'),
('2', 'Agree'), ('3', 'Neutral'), ('4', 'Disagree'), ('5', 'Strongly Disagree'))})>
If I reload the page, it has this value:
<app.survey.forms.SingleRadioFieldForm object at 0x110788d30>
I don't notice anything else different in the state of the program between the two page loads.
What is causing this the first time and how can I fix it?
While I still don't know why the original function wasn't working on first page load, but did on a reload, I went about this in another way and solved the problem. Instead of setting the fields within __init__, I subclassed within the function and edited the class directly.
#bp.route('/survey/<string:slug>', methods=['GET', 'POST'])
def survey(slug):
class F(FieldsRequiredForm):
pass
...
if None in answers.values():
question = get_next_question()
F.question_id = HiddenField(default=question.id)
if question.category == 'word':
F.answer = StringField(question.question)
elif question.category == 'likert':
F.answer = RadioField(question.question, choices=tuple(likert().items()))
F.submit = SubmitField('Submit')
else:
F.answer = StringField()
form = F()
...

wxpython wx.combobox save wx.StaticText view help me

import wx
import sqlite3
class Frame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None)
self.panel = wx.Panel(self)
self.text = wx.StaticText(self.panel)
self.conn = sqlite3.connect("test.db")
self.cursor = self.conn.cursor()
self.autoRefersh()
def autoRefersh(self):
self.LoadList()
wx.CallLater(1000, self.autoRefersh)
def LoadList(self):
self.cursor.execute("SELECT *FROM CLINIC1")
for date1 in self.cursor: pass
self.staticText2_1 = wx.StaticText(self.panel, label=date1[1], style=wx.ALIGN_CENTER, pos=(100,100))
if __name__ == '__main__':
app = wx.App()
frame = Frame()
frame.Show()
app.MainLoop()
combobox data sqlite3 save in why panel show Why it looks different bug??
I do not know why this is happening.
You missed one crucial step, getting the data itself.
You are using the cursor object not the data returned by the cursor.
def LoadList(self):
self.cursor.execute("SELECT *FROM CLINIC1")
data = self.cursor.fetchall()
for date1 in data: pass
self.staticText2_1 = wx.StaticText(self.panel, label=date1[1], style=wx.ALIGN_CENTER, pos=(100,100))
AS you are "passing" in your for loop perhaps what you actually want is only a single record, in which case
data = self.cursor.fetchone()
and drop the for loop
Even better, read the tutorial
https://www.blog.pythonlibrary.org/2012/07/18/python-a-simple-step-by-step-sqlite-tutorial/
In the heading of your question you mention combobox, so I assume that you want to replace the statictext with a combobox. The following should get you started, I'll leave the wx.EVT_COMBOBOX event binding for you to add, as you will need it to do something when you select an item.
import wx
import sqlite3
class Frame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None)
self.selected_data=[]
self.panel = wx.Panel(self)
self.combo = wx.ComboBox(self.panel,-1,choices=self.selected_data, size=(130,30))
self.conn = sqlite3.connect("test.db")
self.cursor = self.conn.cursor()
self.combo.SetValue("Choose an Item")
self.autoRefresh()
def autoRefresh(self):
self.LoadList()
def LoadList(self):
self.combo.Clear()
self.cursor.execute("SELECT * FROM CLINIC1")
data = self.cursor.fetchall()
for date1 in data:
self.selected_data.append(date1[1])
for i in self.selected_data:
self.combo.Append(i)
if __name__ == '__main__':
app = wx.App()
frame = Frame()
frame.Show()
app.MainLoop()
Edit:
It should look like this.

How to show a QDialog

I need to show a find dialog after pressing Ctrl+F in QWidget, which contains a QTableView. The find dialog will search in the first column of the table to find the matches.
I can show the QMessageBox after pressing Ctrl+F with the following code:
class Widget(QWidget):
def __init__(self,md,parent=None):
QWidget.__init__(self,parent)
layout=QVBoxLayout(self)
# initially construct the visible table
tv = QTableView()
# uncomment this if the last column shall cover the rest
tv.horizontalHeader().setStretchLastSection(True)
tv.show()
# set black grid lines
self.setStyleSheet("gridline-color: rgb(39, 42, 49)")
# construct the Qt model belonging to the visible table
model = NvmQtModel(md)
tv.setModel(model)
tv.resizeRowsToContents()
tv.resizeColumnsToContents()
# set the shortcut ctrl+F for find in menu
shortcut = QShortcut(QKeySequence('Ctrl+f'), self)
shortcut.activated.connect(self.handleFind)
# delegate for decimal
delegate = NvmDelegate()
tv.setItemDelegate(delegate)
self.setGeometry(200,200,600,600) # adjust this later
layout.addWidget(tv)
# set window title
self.setWindowTitle("TITLE")
# find function: search in the first column of the table
def handleFind(self):
reply = QMessageBox.question(
self, 'Find', 'Find Dialog',
QMessageBox.Yes | QMessageBox.No)
if reply == QMessageBox.Yes:
print('Yes')
else:
print('No')
Then I changed the QMessageBox to a QDialog, but now it does not work. I would appreciate if you could tell me where I am not doing it correctly:
class Widget(QWidget):
def __init__(self,md,parent=None):
QWidget.__init__(self,parent)
layout=QVBoxLayout(self)
# initially construct the visible table
tv = QTableView()
# uncomment this if the last column shall cover the rest
tv.horizontalHeader().setStretchLastSection(True)
tv.show()
# set black grid lines
self.setStyleSheet("gridline-color: rgb(39, 42, 49)")
# construct the Qt model belonging to the visible table
model = NvmQtModel(md)
tv.setModel(model)
tv.resizeRowsToContents()
tv.resizeColumnsToContents()
# set the shortcut ctrl+F for find in menu
shortcut = QShortcut(QKeySequence('Ctrl+f'), self)
shortcut.activated.connect(self.handleFind)
# delegate for decimal
delegate = NvmDelegate()
tv.setItemDelegate(delegate)
self.setGeometry(200,200,600,600) # adjust this later
layout.addWidget(tv)
# set window title
self.setWindowTitle("TITLE")
# find function: search in the first column of the table
def handleFind(self):
findDialog = QDialog()
findLabel = QLabel("Find what", findDialog)
findField = QLineEdit(findDialog)
findButton = QPushButton("Find", findDialog)
closeButton = QPushButton("Close", findDialog)
findDialog.show()
If you want the Dialog be a modal Dialog, call findDialog.exec_():
from PyQt4.QtGui import *
def handleFind():
findDialog = QDialog()
#findDialog.setModal(True)
findLabel = QLabel("Find what", findDialog)
findField = QLineEdit(findDialog)
findButton = QPushButton("Find", findDialog)
closeButton = QPushButton("Close", findDialog)
#findDialog.show()
findDialog.exec_()
app = QApplication([])
b = QPushButton("click me")
b.clicked.connect(handleFind)
b.show()
app.exec_()

Resources