Uncheck all boxes in exclusive group - python

I have two check boxes which are part of a button group. I want to be able to select one, the other, or none. To this end, I have the following:
import sys
from PySide2 import QtCore, QtWidgets
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle('Check Problems')
self.init_widgets()
self.init_layout()
def init_widgets(self):
self.check1_label = QtWidgets.QLabel('Check1')
self.check1 = QtWidgets.QCheckBox()
self.check2_label = QtWidgets.QLabel('Check2')
self.check2 = QtWidgets.QCheckBox()
self.check_buttongroup = QtWidgets.QButtonGroup()
self.check_buttongroup.addButton(self.check1)
self.check_buttongroup.addButton(self.check2)
self.check_buttongroup.buttonPressed.connect(self.check_buttongroup_pressed)
def init_layout(self):
check1_layout = QtWidgets.QHBoxLayout()
check1_layout.addWidget(self.check1_label)
check1_layout.addWidget(self.check1)
check2_layout = QtWidgets.QHBoxLayout()
check2_layout.addWidget(self.check2_label)
check2_layout.addWidget(self.check2)
check_layout = QtWidgets.QVBoxLayout()
check_layout.addLayout(check1_layout)
check_layout.addLayout(check2_layout)
# Central widget
centralWidget = QtWidgets.QWidget()
centralWidget.setLayout(check_layout)
self.setCentralWidget(centralWidget)
def check_buttongroup_pressed(self, button):
print('\nIs this check1? ', button == self.check1, flush=True)
print('Status when pressed: ', button.isChecked(), flush=True)
if button.isChecked():
print('Button isChecked: ', button.isChecked(), flush=True)
print('Changing button check state...', flush=True)
button.group().setExclusive(False)
button.setChecked(False)
print('Button isChecked: ', button.isChecked(), flush=True)
button.group().setExclusive(True)
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
mainWin = MainWindow()
mainWin.show()
sys.exit(app.exec_())
No boxes are checked initially. Clicking check1 produces:
Is this check1? True
Status when pressed: False
This is expected. The box was unchecked initially. Having clicked it, however, the box is now checked. When I click check1 again, I expect it to uncheck, leaving both boxes unchecked. Now, clicking check1, I see:
Is this check1? True
Status when pressed: True
Button isChecked: True
Changing button check state...
Button isChecked: False
This is as expected. What is unexpected, however, is check1 is still checked!
Clicking a third time produces:
Is this check1? True
Status when pressed: True
Button isChecked: True
Changing button check state...
Button isChecked: False
Why does check1 not uncheck as expected? Is button.isChecked() lying to me or is setChecked(False) not doing its job? Am I mistaken somewhere?
I have tried this with PySide2==5.15.0, PySide2==5.13, PySide6, and PyQt5==5.15 with the same result, so I assume this is how it's supposed to behave and not some Qt implementation error.

The solution is to change the property exclusive to False if when the buttonPressed signal is emitted the button is checked and set that property to true when the buttonClicked is emitted.
def init_widgets(self):
# ...
self.check_buttongroup = QtWidgets.QButtonGroup()
self.check_buttongroup.addButton(self.check1)
self.check_buttongroup.addButton(self.check2)
self.check_buttongroup.buttonPressed.connect(self.handle_pressed)
self.check_buttongroup.buttonClicked.connect(self.handle_clicked)
def handle_pressed(self, button):
button.group().setExclusive(not button.isChecked())
def handle_clicked(self, button):
button.group().setExclusive(True)

Related

How to toggle fullscreen mode?

I want my application to toggle fullscreen every time you click on the menu item. So if you click once, it becomes fullscreen, if you click again, it becomes normal again. I tried the following but after I clicked it again, it wouldn't switch.
def Fullscreen(self):
self.fullscreen = False
if not self.fullscreen:
self.root.wm_attributes("-fullscreen", True)
else:
self.root.wm_attributes("-fullscreen", False)
You are missing a key part here. Nothing changes full screen back to True.
Here is a simple example of what you could do to toggle full screen.
import tkinter as tk
class App(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
tk.Button(self, text="Toggle Fullscreen", command=self.fullscreen_toggle).pack()
self.fullscreen = False
def fullscreen_toggle(self):
if self.fullscreen == False:
self.wm_attributes("-fullscreen", True)
self.fullscreen = True
else:
self.wm_attributes("-fullscreen", False)
self.fullscreen = False
app = App()
app.mainloop()

Use one QPushButton with two QLineEdits, depending on last focus

I have a window, which has two QLineEdits in it. They are Line 1 and Line 2. I have a Backspace QPushButton which is to be pressed. I want some code which, when the backspace is pressed, will delete the text from the desired QLineEdit. This is to be done based on which one is focused at the time.
I understand that currently my code will backspace line1, however I want it to delete whichever line edit most recently had focus (i.e. if line1 was selected before backspace, it will get backspaced, if line 2 was the last in focus, then it will be backspaced).
I'm thinking it requires an if statement or 2, not sure though. How do I choose which line edit is deleted based on which one last had focus?
from PySide import QtGui, QtCore
from PySide.QtCore import*
from PySide.QtGui import*
class MainWindow(QtGui.QMainWindow): #The Main Window Class Maker
def __init__(self,):
QtGui.QMainWindow.__init__(self)
QtGui.QApplication.setStyle(('cleanlooks'))
mfont = QFont()
mfont.setFamily("BankGothic LT")
mfont.setPointSize(40)
mfont.setBold(True)
xfont = QFont()
xfont.setFamily("BankGothic LT")
xfont.setPointSize(40)
xfont.setLetterSpacing(QFont.AbsoluteSpacing, 15)
self.line1 = QLineEdit("Line 1", self)
self.line1.setFixedSize(460, 65)
self.line1.setFont(xfont)
self.line1.move(10,10)
self.line2 = QLineEdit("Line 2", self)
self.line2.setFixedSize(460, 65)
self.line2.setFont(xfont)
self.line2.move(10,200)
#BackSpace button
back = QPushButton("BackSpace", self)
back.move(100,100)
back.setFixedSize(300,75)
back.setFont(mfont)
back.clicked.connect(self.line1.backspace)
if __name__ == '__main__':
import sys
app = QtGui.QApplication(sys.argv)
window = MainWindow()
window.setWindowTitle("BackSpace")
window.resize(480, 400)
window.setMaximumSize(480,400)
window.setMinimumSize(480,400)
window.show()
sys.exit(app.exec_())
You can accomplish this by utilizing the editingFinished signal and some manipulation of which line edit is connected to your backspace function.
I'll post then entire code block and then explain the changes I made below it.
class MainWindow(QtGui.QMainWindow):
def __init__(self,):
QtGui.QMainWindow.__init__(self)
QtGui.QApplication.setStyle(('cleanlooks'))
mfont = QFont()
mfont.setFamily("BankGothic LT")
mfont.setPointSize(40)
mfont.setBold(True)
xfont = QFont()
xfont.setFamily("BankGothic LT")
xfont.setPointSize(40)
xfont.setLetterSpacing(QFont.AbsoluteSpacing, 15)
self.line1 = QLineEdit("Line 1", self)
self.line1.setFixedSize(460, 65)
self.line1.setFont(xfont)
self.line1.move(10,10)
self.line2 = QLineEdit("Line 2", self)
self.line2.setFixedSize(460, 65)
self.line2.setFont(xfont)
self.line2.move(10,200)
self.recent_line = self.line2
self.previous_line = self.line1
#BackSpace button
self.back = QPushButton("BackSpace", self)
self.back.move(100,100)
self.back.setFixedSize(300,75)
self.back.setFont(mfont)
self.back.clicked.connect(self.recent_line.backspace)
self.line1.editingFinished.connect(self.last_lineedit)
self.line2.editingFinished.connect(self.last_lineedit)
def last_lineedit(self):
if isinstance(self.sender(), QLineEdit):
self.recent_line, self.previous_line = self.previous_line, self.recent_line
self.back.clicked.disconnect(self.previous_line.backspace)
self.back.clicked.connect(self.recent_line.backspace)
The first change that I've made is to include two new variables so that we can keep track of which QLineEdit was focused on last:
self.recent_line = self.line2
self.previous_line = self.line1
Next, I changed your back widget to be self.back, because we are going to need it outside of __init__
self.back = QPushButton("BackSpace", self)
self.back.move(100,100)
self.back.setFixedSize(300,75)
self.back.setFont(mfont)
self.back.clicked.connect(self.recent_line.backspace)
Then we are going to set up both line1 and line2 to the editingFinished signal.
This signal is emitted when the Return or Enter key is pressed or the line edit loses focus.
We'll be utilizing the "loses focus" part, because when the self.back button is pressed, the QLineEdit has lost focus.
Finally we get to the function that is going to keep track of which QLineEdit is connected to the backspace button at any given time.
def last_lineedit(self):
if isinstance(self.sender(), QLineEdit):
self.recent_line, self.previous_line = self.previous_line, self.recent_line
self.back.clicked.disconnect(self.previous_line.backspace)
self.back.clicked.connect(self.recent_line.backspace)
Within this function, we fist ensure that only one of the QLineEdits are sending the signal (just in case you connect something else to this signal that isn't a QLineEdit).
Next, we swap which QLineEdit was most recently focused on:
self.recent_line, self.previous_line = self.previous_line, self.recent_line
Then we disconnect from the previous line and connect to the new line. These last two lines are the magic that allows you to delete from both lines based on which had focus most recently. These lines are also why we changed to self.back, instead of leaving it at back. The locally scoped back wasn't accessible from the last_lineedit function.
It would be best if the backspace button didn't steal focus. That way, the caret will stay visible in the line-edit that has focus, and the user can easily see exactly what is happening. Doing it this way also makes the code much simpler:
back.setFocusPolicy(QtCore.Qt.NoFocus)
back.clicked.connect(self.handleBackspace)
def handleBackspace(self):
widget = QtGui.qApp.focusWidget()
if widget is self.line1 or widget is self.line2:
widget.backspace()
Ok guys, so I kept working on this in order to find a useful situation, where one would use this sort of functionality.
Say you were trying to create a login form for a touch screen, but you had no onscreen keyboard installed, you can 'create' one. This is what the intended use was for.
I've sort of tested this, and fixed any bugs I saw, but hey, feel free to use it. I noticed that heaps of examples existed for calculators, but no real examples existed for Keypad or Numberpad entry. Enjoy!
from PySide import QtGui, QtCore
from PySide.QtCore import*
from PySide.QtGui import*
class MainWindow(QtGui.QMainWindow): #The Main Window Class Maker
def __init__(self,):
QtGui.QMainWindow.__init__(self)
QtGui.QApplication.setStyle(('cleanlooks'))
U = QLabel("U:", self)
U.move(10,10)
P = QLabel("P:", self)
P.move(10,50)
self.line1 = QLineEdit("", self)
self.line1.move(20,10)
self.line1.setReadOnly(True)
self.line2 = QLineEdit("", self)
self.line2.move(20,50)
self.line2.setReadOnly(True)
self.line2.setEchoMode(QLineEdit.Password)
#PushButtons
back = QPushButton("<", self)
back.move(100,80)
back.setFocusPolicy(QtCore.Qt.NoFocus)
back.setFixedSize(20,20)
one = QPushButton('1', self)
one.move(10,80)
one.setFocusPolicy(QtCore.Qt.NoFocus)
one.setText("1")
one.setFixedSize(20,20)
two = QPushButton('2', self)
two.move(40,80)
two.setFocusPolicy(QtCore.Qt.NoFocus)
two.setFixedSize(20,20)
three = QPushButton('3', self)
three.move(70,80)
three.setFocusPolicy(QtCore.Qt.NoFocus)
three.setFixedSize(20,20)
four = QPushButton('4', self)
four.move(10,110)
four.setFocusPolicy(QtCore.Qt.NoFocus)
four.setFixedSize(20,20)
five = QPushButton('5', self)
five.move(40,110)
five.setFocusPolicy(QtCore.Qt.NoFocus)
five.setFixedSize(20,20)
six = QPushButton('6', self)
six.move(70,110)
six.setFocusPolicy(QtCore.Qt.NoFocus)
six.setFixedSize(20,20)
seven = QPushButton('7', self)
seven.move(10,140)
seven.setFocusPolicy(QtCore.Qt.NoFocus)
seven.setFixedSize(20,20)
eight = QPushButton('8', self)
eight.move(40,140)
eight.setFocusPolicy(QtCore.Qt.NoFocus)
eight.setFixedSize(20,20)
nine = QPushButton('9', self)
nine.move(70,140)
nine.setFocusPolicy(QtCore.Qt.NoFocus)
nine.setFixedSize(20,20)
zero = QPushButton('0', self)
zero.move(100,140)
zero.setFocusPolicy(QtCore.Qt.NoFocus)
zero.setFixedSize(20,20)
enter = QPushButton("E", self)
enter.move(100,110)
enter.setFixedSize(20,20)
enter.setFocusPolicy(QtCore.Qt.NoFocus)
#click Handles
def handleBackspace():
backh = QtGui.qApp.focusWidget()
if backh is self.line1 or backh is self.line2:
backh.backspace()
def handleZero():
zeroh = QtGui.qApp.focusWidget()
if zeroh is self.line1:
zeroh.setText((self.line1.text()+str('0')))
else:
zeroh.setText(self.line2.text()+str('0'))
def handleOne():
oneh = QtGui.qApp.focusWidget()
if oneh is self.line1:
oneh.setText(self.line1.text()+str('1'))
else:
oneh.setText(self.line2.text()+str('1'))
def handleTwo():
twoh = QtGui.qApp.focusWidget()
if twoh is self.line1:
twoh.setText(self.line1.text()+str('2'))
else:
twoh.setText(self.line2.text()+str('2'))
def handleThree():
threeh = QtGui.qApp.focusWidget()
if threeh is self.line1:
threeh.setText(self.line1.text()+str('3'))
else:
threeh.setText(self.line2.text()+str('3'))
def handleFour():
fourh = QtGui.qApp.focusWidget()
if fourh is self.line1:
fourh.setText(self.line1.text()+str('4'))
else:
fourh.setText(self.line2.text()+str('4'))
def handleFive():
fiveh = QtGui.qApp.focusWidget()
if fiveh is self.line1:
fiveh.setText(self.line1.text()+str('5'))
else:
fiveh.setText(self.line2.text()+str('5'))
def handleSix():
sixh = QtGui.qApp.focusWidget()
if sixh is self.line1:
sixh.setText(self.line1.text()+str('6'))
else:
sixh.setText(self.line2.text()+str('6'))
def handleSeven():
sevenh = QtGui.qApp.focusWidget()
if sevenh is self.line1:
sevenh.setText(self.line1.text()+str('7'))
else:
sevenh.setText(self.line2.text()+str('7'))
def handleEight():
eighth = QtGui.qApp.focusWidget()
if eighth is self.line1:
eighth.setText(self.line1.text()+str('8'))
else:
eighth.setText(self.line2.text()+str('8'))
def handleNine():
nineh = QtGui.qApp.focusWidget()
if nineh is self.line1:
nineh.setText(self.line1.text()+str('9'))
else:
nineh.setText(self.line2.text()+str('9'))
#Click Conditions
self.connect(enter, SIGNAL("clicked()"), self.close)
zero.clicked.connect(handleZero)
nine.clicked.connect(handleNine)
eight.clicked.connect(handleEight)
seven.clicked.connect(handleSeven)
six.clicked.connect(handleSix)
five.clicked.connect(handleFive)
four.clicked.connect(handleFour)
three.clicked.connect(handleThree)
two.clicked.connect(handleTwo)
one.clicked.connect(handleOne)
back.clicked.connect(handleBackspace)
if __name__ == '__main__':
import sys
app = QtGui.QApplication(sys.argv)
window = MainWindow()
window.setWindowTitle("LoginWindow")
window.resize(130, 180)
window.setMaximumSize(130, 180)
window.setMinimumSize(130, 180)
window.show()
sys.exit(app.exec_())

Python making gtk.Layout with Scrollbars

How could I have a scrollbar inside a gtk.Layout.
For example, in my code I have:
import pygtk
pygtk.require('2.0')
import gtk
class ScrolledWindowExample:
def __init__(self):
self.window = gtk.Dialog()
self.window.connect("destroy", self.destroy)
self.window.set_size_request(300, 300)
self.scrolled_window = gtk.ScrolledWindow()
self.scrolled_window.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
self.window.vbox.pack_start(self.scrolled_window, True, True, 0)
self.layout = gtk.Layout()
self.scrolled_window.add(self.layout)
self.current_pos = 0
self.add_buttom()
self.window.show_all()
def add_buttom(self, widget = None):
title = str(self.current_pos)
button = gtk.ToggleButton(title)
button.connect_object("clicked", self.add_buttom, None)
self.layout.put(button, self.current_pos, self.current_pos)
button.show()
self.current_pos += 20
def destroy(self, widget):
gtk.main_quit()
if __name__ == "__main__":
ScrolledWindowExample()
gtk.main()
What I really want is to find some way to make the scroll dynamic. See the example that I put above, when you click any button, another button will be added. But the scrollbar doesn't work.
What can I do to get the scroll bars working?
Does it works if you either use gtk.Window() instead of gtk.Dialog(); or execute self.window.run() after self.window.show_all()?
The difference between Dialog and common Window is that Dialog has its own loop which processes events. As you do not run its run() command, this loop never gets the chance to catch the events, so ScrolledWindow does not receives them, and does not change its size.

PyGTK how to click button and open file in pop-up window

I editted the code so that the 3 buttons now show up .Can someone please tell me how to make it so that when I click the button that says Helloworld and application called Helloworld.py will pop-up in another window.Same for the other 2 buttons
!/usr/bin/env python
# menu.py
import pygtk
pygtk.require('2.0')
import gtk
class MenuExample:
def __init__(self):
# create a new window
window = gtk.Window(gtk.WINDOW_TOPLEVEL)
window.set_size_request(200, 100)
window.set_title("GTK Menu Test")
window.connect("delete_event", lambda w,e: gtk.main_quit())
# Init the menu-widget, and remember -- never
# show() the menu widget!!
# This is the menu that holds the menu items, the one that
# will pop up when you click on the "Root Menu" in the app
menu = gtk.Menu()
# Next we make a little loop that makes three menu-entries for
# "test-menu". Notice the call to gtk_menu_append. Here we are
# adding a list of menu items to our menu. Normally, we'd also
# catch the "clicked" signal on each of the menu items and setup a
# callback for it, but it's omitted here to save space.
for i in range(3):
# Copy the names to the buf.
buf = "Test-undermenu - %d" % i
# Create a new menu-item with a name...
menu_items = gtk.MenuItem(buf)
# ...and add it to the menu.
menu.append(menu_items)
# Do something interesting when the menuitem is selected
menu_items.connect("activate", self.menuitem_response, buf)
# Show the widget
menu_items.show()
# This is the root menu, and will be the label
# displayed on the menu bar. There won't be a signal handler attached,
# as it only pops up the rest of the menu when pressed.
root_menu = gtk.MenuItem("Root Menu")
root_menu.show()
# Now we specify that we want our newly created "menu" to be the
# menu for the "root menu"
root_menu.set_submenu(menu)
# A vbox to put a menu and a button in:
vbox = gtk.VBox(False, 0)
window.add(vbox)
vbox.show()
# Create a menu-bar to hold the menus and add it to our main window
menu_bar = gtk.MenuBar()
vbox.pack_start(menu_bar, False, False, 2)
menu_bar.show()
# Create a button to which to attach menu as a popup
button = gtk.Button("HelloWorld")
button.connect_object("event", self.button_press, menu)
vbox.pack_end(button, True, True, 2)
button.show()
button2 = gtk.Button("Scrible")
button2.connect_object("event", self.button_press, menu)
vbox.pack_end(button2, True, True, 2)
button2.show()
button3 = gtk.Button("Final")
button3.connect_object("event", self.button_press, menu)
vbox.pack_end(button3, True, True, 2)
button3.show()
# And finally we append the menu-item to the menu-bar -- this is the
# "root" menu-item I have been raving about =)
menu_bar.append (root_menu)
# always display the window as the last step so it all splashes on
# the screen at once.
window.show()
# Respond to a button-press by posting a menu passed in as widget.
#
# Note that the "widget" argument is the menu being posted, NOT
# the button that was pressed.
def button_press(self, widget, event):
if event.type == gtk.gdk.BUTTON_PRESS:
widget.popup(None, None, None, event.button, event.time)
# Tell calling code that we have handled this event the buck
# stops here.
return True
# Tell calling code that we have not handled this event pass it on.
return False
def button2_press(self, widget, event):
if event.type == gtk.gdk.BUTTON2_PRESS:
widget.popup(None, None, None, event.button, event.time)
return True
return False
def button3_press(self, widget, event):
if event.type == gtk.gdk.BUTTON3_PRESS:
widget.popup(None, None, None, event.button, event.time)
return True
return False
# Print a string when a menu item is selected
def menuitem_response(self, widget, string):
print "%s" % string
def main():
gtk.main()
return 0
if __name__ == "__main__":
MenuExample()
main()
You could do something like this. I'm assuming you just want to execute your .py files, e.g. helloworld.py etc. I'm using Popen from subprocess to execute python (not assuming the py files are executable) scripts. Note that I've edited the script to only have one button, this is just to show you the idea.
import pygtk
pygtk.require('2.0')
import gtk
import subprocess
class Example:
def __init__(self):
window = gtk.Window(gtk.WINDOW_TOPLEVEL)
window.set_size_request(200, 100)
window.set_title("GTK Menu Test")
window.connect("delete_event",
lambda w,e: gtk.main_quit())
vbox = gtk.VBox(False, 0)
window.add(vbox)
vbox.show()
button = gtk.Button("HelloWorld")
button.connect("clicked", self.clicked_helloworld)
vbox.pack_end(button, True, True, 2)
button.show()
window.show_all()
def clicked_helloworld(self, widget):
subprocess.Popen(["python", "helloworld.py"])
def main(self):
gtk.main()
return 0
Example().main()

Catching a click anywhere inside a gtk.Window

consider the following python code:
import gtk
class MainWindow():
def __init__(self):
self.window = gtk.Window()
self.window.show()
if __name__ == "__main__":
main = MainWindow()
gtk.main()
I'd need to catch clicks anywhere inside this gtk.Window().
I haven't found any suitable event (I also tried button-press-event, but it doesn't work), what am I missing?
Thank you!
You can pack a gtk.EventBox into the window. In general, whenever you have troubles catching events, check if gtk.EventBox solves them.
import gtk
class MainWindow():
def __init__(self):
self.window = gtk.Window()
self.box = gtk.EventBox ()
self.window.add (self.box)
self.box.add (gtk.Label ('some text'))
self.window.show_all()
import sys
self.box.connect ('button-press-event',
lambda widget, event:
sys.stdout.write ('%s // %s\n' % (widget, event)))
if __name__ == "__main__":
main = MainWindow()
gtk.main()
Note, however, that event propagation upwards the widget hierarchy will stop if a widget handles event itself. For instance, a parent of gtk.Button won't receive click events from it.
So i have this DrawingArea in Window. And on click i get the callback
self.drawingarea = gtk.DrawingArea()
self.drawingarea.connect ('button-press-event',self.callback)
self.drawingarea.set_events(gtk.gdk.EXPOSURE_MASK
| gtk.gdk.LEAVE_NOTIFY_MASK
| gtk.gdk.BUTTON_PRESS_MASK
| gtk.gdk.POINTER_MOTION_MASK
| gtk.gdk.POINTER_MOTION_HINT_MASK )
self.window.add(self.drawingarea)
Filter the left or right button:
def callback(self, widget, event):
print "clicking... left or right"
if event.button == 1:
print 'OK - clicked left '
#os.system("""wmctrl -s 0""")
return True

Categories

Resources