I'm trying to change buttons icon on specific action. (Clicked, Disabled etc.)
So as an example lets take a button press, If i have a button:
btn = QtGui.QPushButton(" ", self)
btn.resize(100, 100)
btn.move(0, 0)
btn.setIcon(QtGui.QIcon(""))
btn.setIconSize(QtCore.QSize(100, 100))
How can i change its icon when clicked? Do i need to make a clicked signal?
btn.clicked.connect(self.some_function_that_shows_new_icon)
If so, how can i make disabled signal or any other button condition available?
Example:
btn.disabled.connect(self.some_function_that_shows_new_icon)
(Signal that will detect if buttons disabled or not, One above doesn't work)
QIcons can have multiple images for different modes and states. You add multiple QPixmaps to the same QIcon and specify the mode and state for that image.
icon = QIcon()
icon.addPixmap(QPixmap('normal.png'))
icon.addPixmap(QPixmap('disabled.png'), QIcon.Disabled)
icon.addPixmap(QPixmap('clicking.png'), QIcon.Active)
icon.addPixmap(QPixmap('on.png'), QIcon.Normal, QIcon.On)
btn.setIcon(icon)
It depends on whether clicking the button is changing the state of the button (eg. toggling it on or off). If you're using the button to toggle the state of something else, this won't work.
Related
I have a window in PyQt5, where I have a lot of elements and two specific buttons among them. One of the buttons, called "Save", when clicked, takes a screenshot of the window with this code:
w = self.centralwidget
screen = app.primaryScreen()
screenshot = screen.grabWindow(w.winId())
screenshot.save('screenshot.jpg', 'jpg')
The other button, called "Browse", opens a Windows explorer with the folder of the taken screenshot.
The buttons themselves work as intended.
What I want to achieve is, when the "Save" button is clicked, the "Save" and "Browse" buttons to hide, so that they are not visible on the screenshot of the window, then the screenshot to be taken, and then show these buttons on a window again.
I tried the following method (called, when "Save" button is clicked):
def screenshot(self, MainWindow):
self.screenshotButton.hide() #hiding the "Browse" button
self.saveButton.hide() #hiding the "Save" button
w = self.centralwidget
screen = app.primaryScreen()
screenshot = screen.grabWindow(w.winId()) #taking the screenshot
screenshot.save('screenshot.jpg', 'jpg') #saving the screenshot
self.screenshotButton.show() #showing "Browse" button again
self.saveButton.show() #showing "Save" button again
But this does not hide the buttons on the screenshot, they are still visible. I also tried putting time.sleep(5) after using the .(hide) and before taking the screenshot, but it doesn't help.
What can I do about this?
I'm having a problem updating the icon of a button set with QToolButton. The idea is to use the button for a movie player. To play, one presses the button and the icon changes to pause. When pressed again, play is paused and the icon reverts to play. I have some working code, but the problem is that the icon is not updating consistently. If I keep the Qt window in focus, it takes one or two button presses to change the icon to the intended image, by which time the actual image is not the intended image (swapped play/pause).
Here is some minimal example code:
from PyQt5.QtWidgets import QApplication, QVBoxLayout, QWidget, QStyle, QToolButton
class Widget(QWidget):
def __init__(self, parent=None):
super(Widget, self).__init__(parent=parent)
self.play_button = QToolButton(clicked=self.update_button)
self.play_button.setIcon(self.style().standardIcon(QStyle.SP_MediaStop))
self.verticalLayout = QVBoxLayout(self)
self.verticalLayout.addWidget(self.play_button)
self.button_pressed = False
def update_button(self):
if self.button_pressed:
self.play_button.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay))
self.button_pressed = False
print("Button should be set to PLAY. Press is", self.button_pressed)
else:
self.play_button.setIcon(self.style().standardIcon(QStyle.SP_MediaPause))
self.button_pressed = True
print("Button should be set to PAUSE. Press is", self.button_pressed)
if __name__ == '__main__':
app = QApplication(sys.argv)
w = Widget()
w.show()
sys.exit(app.exec_())
In the above I start with a stop icon just to be sure to observe a change (any click should always change the icon). Keeping the window focused, I get the following output:
1st click: "Button should be set to PAUSE. Press is True" (no change in icon)
2nd click: "Button should be set to PLAY. Press is False" (icon changes to pause)
3rd click: "Button should be set to PAUSE. Press is True" (icon changes to play)
(and so on, continues swapping as intended)
I've also noticed that if after each click, I click outside the Qt window, or resize the Qt window, the button icon updates to the correct one. What am I doing wrong? How do I force the icon to update?
This behaviour happens mostly with QToolButton, but QPushButton also give issues (works when focused, but misbehaves/loses track of correct status if I resize the Qt window). Using PyQt 5.12.3 and qt 5.12.5 on macOS.
Seems like this issue is a bug in the Qt implementation for macOS. I tested and it happens with both PyQt5 and PySide2, so it must come from Qt. Forcing a redraw with a call to .repaint() after .setIcon() seems to make the problem go away:
self.play_button.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay))
self.play_button.repaint()
The button size should be controlled by packing HBox in VBox but my two buttons still have size depending on text:
first=Gtk.VBox()
second=Gtk.HBox()
third=Gtk.VBox()
fourth=Gtk.HBox()
but1=Gtk.Button(label="any title")
first.pack_start(second,False,False,0)
third.pack_start(fourth,False,False,0)
first.pack_start(but1,False,False,0)
self.data_wp="title of label"
self.label_data=Gtk.Label(label=self.data_wp)
Gtk.Widget.set_size_request(but1,85,15)
but2=Gtk.Button(label=self.data_wp)
Gtk.Container.add(but2,self.label_data)
Gtk.Widget.set_size_request(but2,85,15)
What am I doing wrong? I add button title from label but it shoudn't be the problem, and I tried to set title directly on button - nothing changed. I tried to use only one set of VBox,HBox, but it gave no effect too.
I think the problem here is that you're trying to resize the button using the set_size_request() method of the Gtk.Widget. But set_size_request() only set the minimum size of the widget, so it can still be larger.
I don't know if there is a method to resize the button, but there are the properties width-request and height-request of the Gtk.Widget that you can use.
In your code, it would be:
bt1.set_property("width-request", 85)
bt1.set_property("height-request", 15)
I am making a box that is similar to the tkMessageBox. There are two simple behaviors that I want to the box to have. First I want the button to be selected automatically when the window opens, and second I want to be able to press enter to push the button. Sounds simple and I realize that I could use the tkinterMessageBox to do this same thing, but this is a stepping stone, and I would like to know how to do this in the future for other things.
The current behavior of the window below is that it opens, and if I press tab it will select the button, but then i can only press the button with the mouse. Again the desired functionality is to have the button selected right away and be able to press the button with the enter key.
import Tkinter, tkMessageBox
from Tkinter import *
def closewindow():
Messagebox.destroy()
Messagebox=Tk()
l3=Label( Messagebox, text="This is your preview! Align camera then press ESC")
b3=Button(Messagebox, text="Okay", command=closewindow)
l3.grid(row=1,column=1)
b3.grid(row=2,column=1)
Messagebox.mainloop()
You can actually do this with just two lines of code:
b3.bind('<Return>', lambda _: closewindow())
b3.focus_set()
The first binds the button to the Enter key and the second sets the application's focus on the button.
Note that I had to use a lambda with the binding to handle the event object that will be sent to the callback. You could however change the definition of closewindow to handle this:
def closewindow(event=None):
Messagebox.destroy()
Now you can just do:
b3.bind('<Return>', closewindow)
For more information on bindings in Tkinter, see Events and Bindings over on Effbot.
So I'm still fairly new to Python, and have been learning for a couple months, but one thing I'm trying to figure out is say you have a basic window...
#!/usr/bin/env python
import sys, os
import pygtk, gtk, gobject
class app:
def __init__(self):
window = gtk.Window(gtk.WINDOW_TOPLEVEL)
window.set_title("TestApp")
window.set_default_size(320, 240)
window.connect("destroy", gtk.main_quit)
window.show_all()
app()
gtk.main()
I wanna right click inside this window, and have a menu pop up like alert, copy, exit, whatever I feel like putting down.
How would I accomplish that?
There is a example for doing this very thing found at http://www.pygtk.org/pygtk2tutorial/sec-ManualMenuExample.html
It shows you how to create a menu attach it to a menu bar and also listen for a mouse button click event and popup the very same menu that was created.
I think this is what you are after.
EDIT: (added further explanation to show how to respond to only right mouse button events)
To summarise.
Create a widget to listen for mouse events on. In this case it's a button.
button = gtk.Button("A Button")
Create a menu
menu = gtk.Menu()
Fill it with menu items
menu_item = gtk.MenuItem("A menu item")
menu.append(menu_item)
menu_item.show()
Make the widget listen for mouse press events, attaching the menu to it.
button.connect_object("event", self.button_press, menu)
Then define the method which handles these events. As is stated in the example in the link, the widget passed to this method is the menu that you want popping up not the widget that is listening for these events.
def button_press(self, widget, event):
if event.type == gtk.gdk.BUTTON_PRESS and event.button == 3:
#make widget popup
widget.popup(None, None, None, event.button, event.time)
pass
You will see that the if statement checks to see if the button was pressed, if that is true it will then check to see which of the buttons was pressed. The event.button is a integer value, representing which mouse button was pressed. So 1 is the left button, 2 is the middle and 3 is the right mouse button. By checking to see if the event.button is 3, you are only responding to mouse press events for the right mouse button.