How do I select items in MenuBar (PyQt/Python) - python

I have created the menu bar shown below as part of a QMainWindow Class and i wanted to run another class or def when i click on 'Save as...' in the Menubar. How could i edit the code below to allow me to do that?? By The way, when i click on Quit, it works (it closes the MainWindow).
def createMenusAndToolbars(self):
fileMenu = self.menuBar().addMenu("File")
for text in (("Save As..."), ("Quit")):
action = QtGui.QAction(text, self)
if text == "Save As...":
text.clicked.connect(self.save)
if text == "Quit":
self.connect(action, QtCore.SIGNAL("triggered()"), self.close)
fileMenu.addAction(action)
def save(self):
save = SaveTest(self)

The code you posted is essentially correct, except for one obviously wrong line. Here's a simplified version which should work as you intended:
def createMenusAndToolbars(self):
fileMenu = self.menuBar().addMenu('File')
fileMenu.addAction('Save As...', self.save)
fileMenu.addAction('Quit', self.quit)
def save(self):
save = SaveTest(self)
NB: the addAction method returns the action it creates, which would allow you to set other properties, if necessary.

Related

Switching Buttons in QMessageBox

I have this code:
def initUI(self):
mainLayout = QVBoxLayout()
# Temporary: Dialog Testing Button #
self.buttonTest = button('Dialog Testing')
self.buttonTest.clicked.connect(self.TestFile)
mainLayout.addWidget(self.buttonTest)
self.setLayout(mainLayout)
# Connects to dialogTesting Button
def dialogMessage(self, message):
dialog = QMessageBox(self)
dialog.setWindowTitle('Sample Text')
dialog.setText(message)
dialog.show()
# Connects with dialogMessage class.
def TestFile(self):
self.dialogMessage("When will non-OK buttons appear?")
return
I get results like this:
How can I change what buttons appear in the popup?
You can change the buttons by using an argument for the buttons parameter when you instantiate a QMessageBox. You use the Standard Button constants. Here is a silly example:
dialog = QMessageBox(self, buttons=QMessageBox.Ok+QMessageBox.Save+QMessageBox.Yes )
If you don't like the choices for standard buttons, you can make your own using addButton. This answer shows how to use addButton.

Adding a function directly to "menuBar" buttons without creating a sub-menu or dropdown

I want to make menu in Python PyQt5 with a function directly linked to it and not with a the sub-menu or dropdown it creates. Here is a snippet from my code:
def create_menu(self):
self.menu = self.menuBar()
self.this = self.menu.addMenu('This')
self.that = self.menu.addMenu('That')
self.menu.show()
self.this.addAction("I want to make it without this", self.there)

In PyQt, how does one get a shared menu and toolbar to talk to the currently active subwindow?

I have an application which has a main window, which can have multiple subwindows. I would like to have one set of QActions in the main window that interact with the currently selected window. For example, the application might be a text editor, and clicking file->save should save the text file the user is currently working on. Additionally, some QActions are checkable, so their checked state should reflect the state of the currently active window.
Here is a minimum working example that has the basic functionality I want, but I suspect there is a better way to do it (further discussion below the code).
import sys
import PyQt4.QtGui as QtGui
class DisplayWindow(QtGui.QWidget):
def __init__(self, parent=None, name="Main Window"):
# run the initializer of the class inherited from
super(DisplayWindow, self).__init__()
self.myLayout = QtGui.QFormLayout()
self.FooLabel = QtGui.QLabel(self)
self.FooLabel.setText(name)
self.myLayout.addWidget(self.FooLabel)
self.setLayout(self.myLayout)
self.is_foo = False
def toggle_foo(self):
self.is_foo = not self.is_foo
if self.is_foo:
self.FooLabel.setText('foo')
else:
self.FooLabel.setText('bar')
class WindowActionMain(QtGui.QMainWindow):
def __init__(self):
super(WindowActionMain, self).__init__()
self.fooAction = QtGui.QAction('Foo', self)
self.fooAction.triggered.connect(self.set_foo)
self.fooAction.setCheckable(True)
menubar = self.menuBar()
fileMenu = menubar.addMenu('&File')
fileMenu.addAction(self.fooAction)
self.toolbar = self.addToolBar('File')
self.toolbar.addAction(self.fooAction)
self.centralZone = QtGui.QMdiArea()
self.centralZone.subWindowActivated.connect(
self.update_current_window)
self.setCentralWidget(self.centralZone)
self.create_dw("Window 1")
self.create_dw("Window 2")
def create_dw(self, name):
dw = DisplayWindow(name=name)
self.centralZone.addSubWindow(dw)
dw.show()
def update_current_window(self):
""" redirect future actions to affect the newly selected window,
and update checked statuses to reflect state of selected window"""
current_window = self.centralZone.activeSubWindow()
if current_window:
self.current_dw = self.centralZone.activeSubWindow().widget()
self.fooAction.setChecked(self.current_dw.is_foo)
def set_foo(self):
self.current_dw.toggle_foo()
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
ex = WindowActionMain()
ex.show()
sys.exit(app.exec_())
My actual version of DisplayWindow could be useful in many different projects, and I want to package it up so that you don't have to add a lot of code to the main window to use it. Therefore, DisplayWindow, all of its functionality and a list of available actions should be in one module, which would be imported in WindowActionMain's module. I should then be able to add more actions for DisplayWindow without changing any code in WindowActionMain. In particular, I don't want to have to write a little function like WindowActionMain.set_foo(self) just to redirect each action to the right place.
Yes, this is possible by handling the QMenu's aboutToShow signal
and considering the QGuiApplication's focusWindow (or however you get that in Qt4).
Example below shows a generic 'Window' menu acting on the frontmost window.
http://doc.qt.io/qt-4.8/qmenu.html#aboutToShow
http://doc.qt.io/qt-5/qguiapplication.html#focusWindow
def on_windowMenu_aboutToShow(self):
self.windowMenu.clear()
self.newWindowAction = QtWidgets.QAction(self)
self.newWindowAction.setShortcut("Ctrl+n")
self.newWindowAction.triggered.connect(self.on_newWindowAction)
self.newWindowAction.setText("New Window")
self.windowMenu.addAction(self.newWindowAction)
self.windowMenu.addSeparator()
playerWindows = [w for w in self.topLevelWindows() if w.type()==QtCore.Qt.Window and w.isVisible()]
for i, w in enumerate(playerWindows):
def action(i,w):
a = QtWidgets.QAction(self)
a.setText("Show Window {num} - {title}".format(num=i+1, title=w.title()))
a.triggered.connect(lambda : w.requestActivate())
a.triggered.connect(lambda : w.raise_())
self.windowMenu.addAction(a)
action(i,w)
self.windowMenu.addSeparator()
self.closeWindowAction = QtWidgets.QAction(self)
self.closeWindowAction.setShortcut("Ctrl+w")
self.closeWindowAction.triggered.connect(lambda : self.focusWindow().close())
self.closeWindowAction.setText("Close")
self.windowMenu.addAction(self.closeWindowAction)

WxPython Login Function

I'm writing a GUI and I'm trying to make a login screen before my main GUI screen but i cant figure out the right way to do this
First i tried to structure it like this:
class GUI(wx.Frame):
#GUI
def __init__(self, parent, id, title):
state = 1
if state ==1:
#Login screen code
elif state == 2:
#Main Screen code
But that didn't work nothing popped up
So i tried creating a whole different smaller window that pops up before the main window but couldn't get that to work
So my question is how can i make a login screen for my GUI correctly
Thank You!!
Here's how I open a Preferences window on first-launch for GooeyPi: My PyInstaller GUI front-end. This can easily be adapted to have a password dialog or frame. I separate out into two functions: check if the user has setup preferences, and open the preferences window. This allows them to change preferences later. I use ShowModal to prevent the user from using the application until they are set.
class GooeyPi(wx.Frame):
def __init__(self, *args, **kwargs):
super(GooeyPi, self).__init__(*args, **kwargs)
self.InitUI()
self.SetSize((460,350))
self.SetTitle('GooeyPi - PyInstaller GUI')
self.Show()
self.CheckFirstRun() # Checks for first run here.
.....
def CheckFirstRun(self):
config = controller.getConfig()
if config['pyidir'] == '':
...
self.OnPreferences(None)
....
def OnPreferences(self, e):
prefdlg = pref.Preferences(None, title='Edit Preferneces')
prefdlg.ShowModal()
prefdlg.Destroy()
and pref.Preferences is definied in a separate module:
class Preferences(wx.Dialog):
def __init__(self, *args, **kw):
super(Preferences, self).__init__(*args, **kw)
self.InitUI()
self.SetSize((380,290))
self.SetTitle("Preferences")
def InitUI(self):
you_get_the_idea...
I recommend using the builtin wx.PasswordEntryDialog and something as simple as Showing or Hiding the main window based on the entry from the password dialog. You could even put the wx.PasswordEntryDialog in a while loop. Something like (untested)
self.Hide()
password = "a passphrase"
entered_password = None
while entered_password != password:
dialog = wx.PasswordEntryDialog(self, "Enter the password", "Please enter the password")
ret_value = dialog.ShowModal()
if ret_value == wx.ID_OK:
entered_password = dialog.GetValue()
else:
self.Close(True)
dialog.Destroy()
# self.Show()

PyQt4 dropdownlist with actions

I want to create a drop down list in PyQt4, that executes an action when an element is selected. Also, some options may not be available at some time. They should still be in the list, but greyed out.
I tried attaching a menu to a QToolButton, but I can not even see the menu.
How is it done?
Thanks!
Nathan
Use a popup. You can trigger a popup anywhere, using the QMenu.exec_ method and passing the point at which you want the menu to appear.
I created a button that remembered where it was clicked, and connected that to the method to create and display the popup.
class MemoryButton(QPushButton):
def __init__(self, *args, **kw):
QPushButton.__init__(self, *args, **kw)
self.last_mouse_pos = None
def mousePressEvent(self, event):
self.last_mouse_pos = event.pos()
QPushButton.mousePressEvent(self, event)
def mouseReleaseEvent(self, event):
self.last_mouse_pos = event.pos()
QPushButton.mouseReleaseEvent(self, event)
def get_last_pos(self):
if self.last_mouse_pos:
return self.mapToGlobal(self.last_mouse_pos)
else:
return None
button = MemoryButton("Click Me!")
def popup_menu():
popup = QMenu()
menu = popup.addMenu("Do Action")
def _action(check):
print "Action Clicked!"
menu.addAction("Action").triggered.connect(_action)
popup.exec_(button.get_last_pos())
button.clicked.connect(popup_menu)
QToolButton has ToolButtonPopupMode enum that controls how it handles menus and multiple actions. When set to QToolButton::MenuButtonPopup, it will display the arrow that is typical of buttons that have menu options.
To use it set the appropriate popup mode and then you can either add a menu to the QToolButton using setMenu or you can add actions using addAction. QToolButton should then respond as expected to clicks on the menu, whether Action generated or an actual QMenu.

Categories

Resources