Adding items to QComboBox - python

I'm trying to add items to two combo boxes.
The code below runs with no errors, I see the list I'm trying to add and "fin" is printed to the terminal, but the combo boxes are showing up empty.
from PyQt5.QtWidgets import QMainWindow
from PyQt5 import QtWidgets
# import GUI from designer file
from main_menu import Ui_main_menu
# import other functions
from add_functions import ChangeLists
class Main(QMainWindow, Ui_main_menu):
def __init__(self, parent=None):
super(Main, self).__init__(parent)
self.setupUi(self)
self.init_lists()
def init_lists(self):
# Team List
team_list_file = open(r'C:\NHLdb_pyqt\files\NHLteams.txt', 'r')
team_list = team_list_file.read().splitlines()
team_list_file.close()
print("team list: ", team_list)
# Initial Player List
player_list_init = "Please Select a Team"
# Populate combo box lists
self.team_select_combobox.addItems(team_list)
self.player_select_combobox.addItem(player_list_init)
# connect combo box to function that will change player list based on team list selection
# self.team_select_combobox.currentTextChanged.connect(ChangeLists.team_changed)
print("fin")
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
main_menu = QtWidgets.QDialog()
ui = Main()
ui.setupUi(main_menu)
# main_menu = Main()
main_menu.show()
sys.exit(app.exec_())

You're using two methods of loading the ui at the same time, the multiple inheritance approach and the "direct approach", and you're actually showing the main_menu instance of QDialog (which doesn't have any init_lists function).
The result is that even if the init_lists is called, it's "shown" (actually, not) in the wrong window, since you're showing the main_menu instance.
Clearly, you should not use both of them, as the first is enough (and usually the most used/suggested), and then show the correct instance object:
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
main_menu = Main()
main_menu.show()
sys.exit(app.exec_())
Do note that there's something else that is wrong with your implementation: you're inheriting from QMainWindow in the Main class, but later you're trying to set up the ui using a QDialog.
Only the base class created in Designer should be used (it doesn't matter what approach you use to load the ui). I can assume that the ui was created using a QDialog (otherwise an exception would have occurred, as a QMainWindow ui would try to use setCentralWidget() which is a function that doesn't exist for QDialog).
So, you either create a new main window in Designer and copy your existing layout in that (if you need the features of a QMainWindow, such as a menu bar, a status bar, dock widgets or toolbars), or you correctly use the QDialog class in the constructor:
class Main(QDialog, Ui_main_menu):
# ...

Related

Pyqt5 multiple widgets

I want to create a pyqt5 application of which, I want to track every button click in the qtextbrowser.
To make it simple to see and also to understand, I want to import different qwidgets to a qmainwindow and build the QMainwindow application in the end.
Evary QWidget has their individual buttons, comboboxes and radiobuttons. I want to track all the activities by appending that activity in a QTextBrowser (which I will import to main window).
(If i click a button_A on a QWidget_1, I want to append the info msg as "Button_A has been clicked" on the QTextBrowser)
I can understand the process of doing this, when we work on a single widget application. But I want to create/build/complile different QWidgets and import that all to a QMainWindow Application (WHich will be my full fledged application).
Does anybody know hoe to track it?
import sys
from PyQt5.QtWidgets import *
from PrintWidget import PrinterWidget
from CameraWidget import CameraWidget
from LaserWidget import LaserWidget
from textbrowser import TextDisplay
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
layout_H = QHBoxLayout()
layout = QVBoxLayout()
layout.addLayout(layout_H)
layout_H.addWidget(PrinterWidget(self))
layout_H.addWidget(CameraWidget(self))
layout.addWidget(LaserWidget(self))
self.browser = TextDisplay()
layout_H.addWidget(self.browser)
self.central_widget = QWidget(self)
self.central_widget.setLayout(layout)
self.setCentralWidget(self.central_widget)
if __name__ == '__main__':
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())
In the above example, I could able to import the textbrowser as a widget to my mainwindow. But I could not ttrack the activities of individual widgets.

Python3 PyQt5 setEnabled of a QAction causing crashes

For a project I'm creating a GUI using Python 3 and PyQt5. Because it has to be usable by people outside of my immediate team, I want to disable actions on the menu until they've already filled out some forms in other parts of the program (e.g. disabling the final solution view when they haven't set up the initial data connection). The issue is that when I try to call the QAction's setEnabled function outside of the function that created it (but still inside the overall class), it's causing my script to crash with no error code, so I'm having trouble understanding the issue. In the snipit below, I'm trying to set the "View Solution" menu option as true. There are some more options in that menu, but I deleted them here to make it more easy to read.
The code is structured something like this:
import sys
from PyQt5.QtWidgets import QMainWindow, QAction, qApp, QApplication, QMessageBox, QStackedLayout
class MediaPlanner(QMainWindow):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
# Menu bar example from: zetcode.com/gui/pyqt5/
exitAction = QAction('&Exit', self)
exitAction.setShortcut('Ctrl+Q')
exitAction.setStatusTip('Exit application')
exitAction.triggered.connect(self.close)
newProject = QAction('&New Project', self)
newProject.setShortcut('Ctrl+N')
newProject.setStatusTip('Start A New Project')
newProject.triggered.connect(self.createNewProject)
openProject = QAction('&Open Project',self)
openProject.setShortcut('Ctrl+O')
openProject.setStatusTip('Open A Saved Project')
openProject.setEnabled(False)
viewSolution = QAction('&View Solution',self)
viewSolution.setStatusTip('View the Current Solution (If Built)')
viewSolution.setEnabled(False)
self.statusBar()
menubar = self.menuBar()
filemenu = menubar.addMenu('&File')
filemenu.addAction(newProject)
filemenu.addAction(openProject)
filemenu.addAction(exitAction)
viewmenu = menubar.addMenu('&View')
viewmenu.addAction(viewSolution)
self.setGeometry(300,300,700,300)
self.setWindowTitle('Menubar')
self.show()
def createNewProject(self):
print('Project Created')
self.viewSolution.setEnabled(True)
if __name__ == '__main__':
app = QApplication(sys.argv)
gui = MediaPlanner()
sys.exit(app.exec_())
The problem is that viewSolution is a variable, but it is not a member of the class so you will not be able to access it through the self instance. One possible solution is to make viewSolution member of the class as shown below:
self.viewSolution = QAction('&View Solution',self)
self.viewSolution.setStatusTip('View the Current Solution (If Built)')
self.viewSolution.setEnabled(False)
...
viewmenu.addAction(self.viewSolution)
Another possible solution is to use the sender() function, this function returns the object that emits the signal, using the following:
def createNewProject(self):
print('Project Created')
self.sender().setEnabled(True)

QtDesigner in combination with PyQt (more specific adding a button to a tab created in QtDesigner

I'm quite new to PyQt and QtDesigner so probably it's easy what I'm tring to do but I couldn't find a working example anywhere.
I've created a GUI in QtDesigner with a tabWidget and multiple tabs (which are QWidgets) named tab,tab_2 etc.
Now I'm trying to add a pushbutton for example to the first tab (called tab). My previous try created the button in a new window..
What is the correct way to do this?
import sys
from PyQt5 import QtWidgets,QtCore, QtGui,uic
from PyQt5.Qt import QPushButton
class Main(QtWidgets.QMainWindow):
def __init__(self):
QtWidgets.QMainWindow.__init__(self)
self.ui = uic.loadUi('example.ui',self)
self.ui.tab.btn1=QtWidgets.QPushButton('buttonn')
self.ui.tab.btn1.show()
if __name__ == '__main__':
from PyQt5.QtWidgets import QApplication
app = QApplication(sys.argv)
window=Main()
window.show()
sys.exit(app.exec_())
The normal way to use QTabWidget is to do the following: Create a
QTabWidget. Create a QWidget for each of the pages in the tab dialog,
but do not specify parent widgets for them. Insert child widgets into
the page widget, using layouts to position them as normal. Call
addTab() or insertTab() to put the page widgets into the tab widget,
giving each tab a suitable label with an optional keyboard shortcut.
Try this:
class Main(QtWidgets.QMainWindow):
def __init__(self):
QtWidgets.QMainWindow.__init__(self)
self.ui = uic.loadUi('example.ui',self)
btn1=QtWidgets.QPushButton('buttonn')
self.ui.tabwidget.addTab(btn1, 'Tab name')
If you have the tabs already created, just create the button as a child of the widget inside the tab:
btn1=QtWidgets.QPushButton('buttonn', self.ui.tab)

Query regarding Pyside

In the below mentioned example when I click on 'Help' submenu under 'View' menu multiple times its creating multiple windows. Can anyone tell me how to resolve this issue?
import sys
from PySide import Qt Gui
from PySide.QtCore import Qt
class Window(QtGui.QMainWindow):
def __init__(self):
QtGui.QMainWindow.__init__(self)
self.menu_bar()
def menu_bar(self):
helpAction = QtGui.QAction('&Help', self)
helpAction.setShortcut('Ctrl+H')
helpAction.triggered.connect(self.add_helpWindow)
menu = self.menuBar().addMenu('View')
menu.addAction(helpAction)
def add_helpWindow(self):
window = QtGui.QMainWindow(self)
window.setWindowTitle('New Window')
window.show()
if __name__ == '__main__':
import sys
app=QtGui.QApplication.instance()
if not app:
app = QtGui.QApplication(sys.argv)
window = Window()
window.resize(300, 300)
window.show()
sys.exit(app.exec_())
You help window is just a QMainWindow, which is not modal and there are no restrictions on the number that can exist. Hence why if you select the help option multiple times, you get multiple windows.
You likely want to use a QMessageBox which has its modal property set. While there is nothing forcing only one dialog to exist at a time, being modal means that the use can only interact with that window so long as it is open. Example:
from Pyside.QtGui import QMessageBox
def add_helpWindow(self):
help_dialog = QMessageBox.information(self, 'Help', 'Some Help Text Here')
help_dialog.setModal(True)
return help_dialog.exec_()
You can also get a more generic dialog box using QDialog, which is the parent class of QMessageBox.
If that's not the behavior you want, you'll need to manually track whether the user has opened that window before, and then connect a signal that is emitted when the user closes the help window to a slot that reset the existence tracker. Here is an example using a non-modal QDialog:
from Pyside.QtGui import QDialog
class Window(QtGui.QMainWindow):
def __init__(self):
QtGui.QMainWindow.__init__(self)
self.menu_bar()
self.help_open = False # Tracks if the help dialog is already open
def help_closed(self):
self.help_open = False
...
def add_helpWindow(self):
if not self.help_open:
self.help_open = True
help_dialog = QDialog(self)
# Any other setup code here
help_dialog.setModal(False)
help_dialog.accepted.connect(self.help_closed)
help_dialog.rejected.connect(self.help_closed)
help_dialog.show()

How to create a new window button PySide/PyQt?

I'm having problems with a "New Window" function in PyQt4/PySide with Python 2.7. I connected a initNewWindow() function, to create a new window, to an action and put it in a menu bar. Once a common function in desktop software. Instead of giving me a new persistent window alongside the other one the new window pops up and closes. The code I'm working on is proprietary so I created an example that does the same thing with the same error below. Is there any way to get this to work? Runs in PySide with Python 2.7. It was written in and tested in Windows.
from PySide.QtCore import QSize
from PySide.QtGui import QAction
from PySide.QtGui import QApplication
from PySide.QtGui import QLabel
from PySide.QtGui import QMainWindow
from PySide.QtGui import QMenuBar
from PySide.QtGui import QMenu
from sys import argv
def main():
application = QApplication(argv)
window = QMainWindow()
window.setWindowTitle('New Window Test')
menu = QMenuBar(window)
view = QMenu('View')
new_window = QAction('New Window', view)
new_window.triggered.connect(initNewWindow)
view.addAction(new_window)
menu.addMenu(view)
label = QLabel()
label.setMinimumSize(QSize(300,300))
window.setMenuBar(menu)
window.setCentralWidget(label)
window.show()
application.exec_()
def initNewWindow():
window = QMainWindow()
window.setWindowTitle('New Window')
window.show()
if __name__ == '__main__':
main()
If a function creates a PyQt object that the application needs to continue using, you will have to ensure that a reference to it is kept somehow. Otherwise, it could be deleted by the Python garbage collector immediately after the function returns.
So either give the object a parent, or keep it as an attribute of some other object. (In principle, the object could also be made a global variable, but that is usually considered bad practice).
Here's a revised version of your example script that demonstrates how to fix your problem:
from PySide import QtGui, QtCore
class Window(QtGui.QMainWindow):
def __init__(self):
QtGui.QMainWindow.__init__(self)
menu = self.menuBar().addMenu(self.tr('View'))
action = menu.addAction(self.tr('New Window'))
action.triggered.connect(self.handleNewWindow)
def handleNewWindow(self):
window = QtGui.QMainWindow(self)
window.setAttribute(QtCore.Qt.WA_DeleteOnClose)
window.setWindowTitle(self.tr('New Window'))
window.show()
# or, alternatively
# self.window = QtGui.QMainWindow()
# self.window.setWindowTitle(self.tr('New Window'))
# self.window.show()
if __name__ == '__main__':
import sys
app = QtGui.QApplication(sys.argv)
window = Window()
window.resize(300, 300)
window.show()
sys.exit(app.exec_())
When initNewWindow() returns, the window variable is deleted and the window's reference count drops to zero, causing the newly created C++ object to be deleted. This is why your window closes immediately.
If you want to keep it open, make sure to keep a reference around. The easiest way to do this is to make your new window a child of the calling window, and set its WA_DeleteOnClose widget attribute (see Qt::WidgetAttribute).

Categories

Resources