Display a specific item in QcomboBox at start up - python-3.x

I have a QcomboBox with some items in it. When Widget starts up and display first item from QcomboBox. How could QcomboBox be forced to display third item ( Index(2)) in the list by start up?
from PyQt5 import QtWidgets, QtGui
class combo(QtWidgets.QWidget):
def __init__(self, parent = None):
super(combo, self).__init__(parent)
layout = QtWidgets.QHBoxLayout(self)
self.cb = QtWidgets.QComboBox()
self.cb.addItems(["1", "2", "3","4"])
layout.addWidget(self.cb)
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
ex = combo()
ex.show()
sys.exit(app.exec_())

The current item can be set with setCurrentIndex().
from PyQt5 import QtWidgets, QtGui
class combo(QtWidgets.QWidget):
def __init__(self, parent = None):
super(combo, self).__init__(parent)
layout = QtWidgets.QHBoxLayout(self)
self.cb = QtWidgets.QComboBox()
self.cb.addItems(["1", "2", "3","4"])
self.cb.setCurrentIndex(2) # <---
layout.addWidget(self.cb)
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
ex = combo()
ex.show()
sys.exit(app.exec_())

Related

How to select row on cursor move?

I want to imitate list walking with arrow keys, I mean to select row when cursor goes up or down with arrow keys, like it happens when I click right-mouse-button on cell in this code, but keyPressEvent does not fires when I use arrows keys.
import sys
from PySide6 import QtCore
from PySide6.QtGui import QKeyEvent
from PySide6.QtWidgets import QMainWindow, QApplication, QTableWidgetItem, QTableWidget, QVBoxLayout, QWidget
from loguru import logger
class TableWindow(QMainWindow):
def __init__(self, data, parent=None):
super(TableWindow, self).__init__(parent)
self.table_widget = QTableWidget()
self.table_widget.cellClicked.connect(self.clicked)
self.populate_cells(data)
layout = QVBoxLayout()
layout.addWidget(self.table_widget)
widget = QWidget()
widget.setLayout(layout)
self.setCentralWidget(widget)
def keyPressEvent(self, event) -> None:
logger.info(f"{event.key()=}")
def clicked(self, row, col):
logger.info(f"{row}, {col}")
self.table_widget.selectRow(row)
def populate_cells(self, data):
self.table_widget.setRowCount(len(data))
self.table_widget.setColumnCount(len(data[0]))
for row in range(len(data)):
for col in range(len(data[0])):
value = data[row][col]
self.table_widget.setItem(row, col, QTableWidgetItem(value))
if __name__ == "__main__":
data_sample = [
["customer1", "address1"],
["customer2", "address2"]
]
app = QApplication(sys.argv)
window = TableWindow(data_sample)
window.show()
sys.exit(app.exec())
I think the issue is that you are listening for keyPressEvents on the main window when you want to be listening for them on the QTableWidget.
What you can do is subclass QTableWidget and reimplement the keyPressEvent method.
For Example:
class TableWidget(QTableWidget):
def keyPressEvent(self, event):
logger.info(f"{event.key()=}")
super().keyPressEvent(event)
class TableWindow(QMainWindow):
def __init__(self, data, parent=None):
super(TableWindow, self).__init__(parent)
self.table_widget = TableWidget()
self.table_widget.cellClicked.connect(self.clicked)
self.populate_cells(data)
layout = QVBoxLayout()
layout.addWidget(self.table_widget)
widget = QWidget()
widget.setLayout(layout)
self.setCentralWidget(widget)
def clicked(self, row, col):
logger.info(f"{row}, {col}")
self.table_widget.selectRow(row)
def populate_cells(self, data):
self.table_widget.setRowCount(len(data))
self.table_widget.setColumnCount(len(data[0]))
for row in range(len(data)):
for col in range(len(data[0])):
value = data[row][col]
self.table_widget.setItem(row, col, QTableWidgetItem(value))
if __name__ == "__main__":
data_sample = [
["customer1", "address1"],
["customer2", "address2"]
]
app = QApplication(sys.argv)
window = TableWindow(data_sample)
window.show()
sys.exit(app.exec())

PyQt5: QLineEdit doesn't show inside a QGroupBox

I'm creating a PyQt5 application in which I want to put some of QLineEdit widgets inside a QGroupBox.
When I run my application, GroupBox is visible and LineEdit is not.
In CreateLinesEdit() I commented a line which sets the line edit visible, but it opens lineEdit in a new window.
from PyQt5.QtWidgets import QGroupBox, QApplication, QLineEdit, QVBoxLayout, QWidget, QHBoxLayout
import sys
class Window(QWidget):
def __init__(self):
super().__init__()
self.InitWindow()
def InitWindow(self):
self.BoxLayout()
self.AddBox()
self.CreateLinesEdit()
self.show()
def BoxLayout(self):
self.groupBoxScreen = QGroupBox()
self.vbox = QVBoxLayout()
self.vbox_screenGame = QVBoxLayout()
self.hbox_lineEdit = QHBoxLayout()
def AddBox(self):
self.vbox_screenGame.addItem(self.hbox_lineEdit)
self.groupBoxScreen.setLayout(self.vbox_screenGame)
self.vbox.addWidget(self.groupBoxScreen)
self.setLayout(self.vbox)
def CreateLinesEdit(self):
self.lines_edit = []
for i in range(0, 4):
LineEdit = QLineEdit()
# LineEdit.setVisible(True)
self.lines_edit.append(LineEdit)
self.hbox_lineEdit.addWidget(self.lines_edit[i])
if __name__ == "__main__":
App = QApplication(sys.argv)
window = Window()
sys.exit(App.exec())

How can I share data with a pyside2 slot function?

I have a PySide2 GUI application with a QPushButton button with a #Slot function connected to it. How can I share data with the function?
from PySide2.QtCore import Slot
from PySide2.QtWidgets import QApplication, QMainWindow, QWidget, QPushButton, QVBoxLayout
#Slot()
def button_XYZ_callback():
# Function which is executed when the button XYZ is clicked.
# I'd like to access the __main__s context data "parent_data" here.
pass
if __name__ == '__main__':
# parent context data what I want to access (read only)
parent_data = "blub"
application = QApplication(sys.argv)
window = QMainWindow()
central_widget = QWidget()
xyz_button = QPushButton("XYZ", central_widget)
xyz_button.clicked.connect(button_xyz_callback)
layout = QVBoxLayout(central_widget)
layout.addWidget(xyz_button)
window.show()
sys.exit(application.exec_())
Per Python's LEGB rule, the global variable parent_data is accessible from within the button_XYZ_callback function.
If, however, you wish to reduce the function's dependence on global variables, the standard technique is to define a class, and use class or instance attributes to store what was before global values:
# based on code from https://wiki.qt.io/Qt_for_Python_Tutorial_ClickableButton
import sys
from PySide2 import QtCore, QtWidgets, QtGui
class MyWidget(QtWidgets.QWidget):
def __init__(self, data):
QtWidgets.QWidget.__init__(self)
self.data = data
self.button = QtWidgets.QPushButton("Click me!")
self.text = QtWidgets.QLabel("Hello World")
self.text.setAlignment(QtCore.Qt.AlignCenter)
self.layout = QtWidgets.QVBoxLayout()
self.layout.addWidget(self.text)
self.layout.addWidget(self.button)
self.setLayout(self.layout)
self.button.clicked.connect(self.button_XYZ_callback)
#QtCore.Slot()
def button_XYZ_callback(self):
print(self.data)
if __name__ == "__main__":
parent_data = "blub"
app = QtWidgets.QApplication(sys.argv)
widget = MyWidget(data=parent_data)
widget.show()
sys.exit(app.exec_())
Alternatively, if the data is known before the callback is to be defined, you could use a function factory to place the data in the enclosing scope of the callback:
import sys
from PySide2.QtCore import Slot
from PySide2.QtWidgets import QApplication, QPushButton
def make_callback(data):
#Slot()
def button_XYZ_callback():
print(data)
return button_XYZ_callback
if __name__ == "__main__":
parent_data = "blub"
# https://wiki.qt.io/Qt_for_Python_Tutorial_ClickableButton
app = QApplication(sys.argv)
button = QPushButton("Click me")
button.clicked.connect(make_callback(parent_data))
button.show()
app.exec_()

How to make "finish" button in QStackedWidget

I trying to create "Finish" button in QStackedWidget.
In a "checkButtons" function i checking current page index and set click events and text. I tried to check it by class name, but it doesn't work too.
Here is a code:
import sys
from PyQt5.QtGui import QIcon
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import (QApplication, QDialog, QComboBox, QStackedWidget, QWidget,
QPushButton, QLabel, QVBoxLayout, QHBoxLayout, QStyle)
class Main(QDialog):
def __init__(self, parent=None):
super(Main, self).__init__(parent)
# Main window setup
self.setWindowTitle("Stacked widget example")
self.setWindowIcon(self.style().standardIcon(QStyle.SP_FileDialogNewFolder))
self.setMinimumSize(400, 400)
self.setMaximumSize(640, 480)
self.rootVBox = QVBoxLayout()
self.rootHBox = QHBoxLayout()
self.rootHBox.addStretch()
self.rootVBox.addStretch()
self.pages = [FirstPage, SecondPage]
self.stacked = QStackedWidget(self)
for i in self.pages: self.stacked.addWidget(i(self))
self.pageState = True
self.buttonNext = QPushButton("Next")
self.buttonNext.clicked.connect(self.buttonNextConnect)
self.buttonBack = QPushButton("Back")
self.buttonBack.clicked.connect(self.buttonBackConnect)
self.rootHBox.addWidget(self.buttonBack)
self.rootHBox.addWidget(self.buttonNext)
self.rootVBox.addLayout(self.rootHBox)
self.setLayout(self.rootVBox)
def checkButtons(self):
print(self.stacked.currentIndex())
# I tried to check self.stacked.currentIndex() but it didn't work too
# if self.stacked.currentWidget().__class__ == self.pages[-1]:
if self.stacked.currentIndex() == len(self.pages) - 1:
self.buttonNext.setText("Finish")
self.buttonNext.clicked.connect(self.close)
elif self.stacked.currentIndex() < len(self.pages) - 1:
self.buttonNext.setText("Next")
self.buttonNext.clicked.connect(self.buttonNextConnect)
def buttonNextConnect(self):
self.stacked.setCurrentIndex(self.stacked.currentIndex() + 1)
self.checkButtons()
def buttonBackConnect(self):
self.stacked.setCurrentIndex(self.stacked.currentIndex() - 1)
self.checkButtons()
def finish(self):
self.close()
class FirstPage(QWidget):
def __init__(self, parent=None):
super(FirstPage, self).__init__(parent)
label = QLabel("First page")
rootVBox = QVBoxLayout()
rootHBox = QHBoxLayout()
rootHBox.addWidget(label)
rootVBox.addLayout(rootHBox)
self.setLayout(rootVBox)
class SecondPage(QWidget):
def __init__(self, parent=None):
super(SecondPage, self).__init__(parent)
label = QLabel("Second page")
rootVBox = QVBoxLayout()
rootHBox = QHBoxLayout()
rootHBox.addWidget(label)
rootVBox.addLayout(rootHBox)
self.setLayout(rootVBox)
if __name__ == '__main__':
app = QApplication(sys.argv)
main = Main()
main.show()
sys.exit(app.exec_())
If you try to press "next", "back" and then "next" again a program will be close. So, how can i fix it? Should i just make control buttons for each widget?
You must use the currentChanged signal of the QStackedWidget to know what page you are on and thus change the text, but in the buttonNextConnect slot you should check if you are already on the last page before switching to a new page, if you are then call to finish and if you do not change to another page
class Main(QDialog):
def __init__(self, parent=None):
super(Main, self).__init__(parent)
# Main window setup
self.setWindowTitle("Stacked widget example")
self.setWindowIcon(self.style().standardIcon(QStyle.SP_FileDialogNewFolder))
self.setMinimumSize(400, 400)
self.setMaximumSize(640, 480)
rootVBox = QVBoxLayout(self)
rootHBox = QHBoxLayout()
rootHBox.addStretch()
rootVBox.addStretch()
self.pages = [FirstPage, SecondPage]
self.stacked = QStackedWidget(self)
for i in self.pages: self.stacked.addWidget(i(self))
self.buttonNext = QPushButton("Next")
self.buttonNext.clicked.connect(self.buttonNextConnect)
self.buttonBack = QPushButton("Back")
self.buttonBack.clicked.connect(self.buttonBackConnect)
rootHBox.addWidget(self.buttonBack)
rootHBox.addWidget(self.buttonNext)
rootVBox.addLayout(rootHBox)
self.stacked.currentChanged.connect(self.on_currentChanged)
def buttonNextConnect(self):
if self.stacked.currentIndex() == self.stacked.count() -1:
self.finish()
if self.stacked.currentIndex() < self.stacked.count() -1:
self.stacked.setCurrentIndex(self.stacked.currentIndex() + 1)
def buttonBackConnect(self):
if self.stacked.currentIndex() > 0:
self.stacked.setCurrentIndex(self.stacked.currentIndex() - 1)
def on_currentChanged(self, index):
if index == self.stacked.count() -1:
self.buttonNext.setText("Finish")
else:
self.buttonNext.setText("Next")
def finish(self):
self.close()
Another option is to use QWizard and QWizardPage:
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
class Main(QtWidgets.QWizard):
def __init__(self, parent=None):
super(Main, self).__init__(parent)
buttons = [
QtWidgets.QWizard.Stretch,
QtWidgets.QWizard.BackButton,
QtWidgets.QWizard.NextButton,
QtWidgets.QWizard.FinishButton
]
self.setButtonLayout(buttons)
self.addPage(FirstPage())
self.addPage(SecondPage())
class FirstPage(QtWidgets.QWizardPage):
def __init__(self, parent=None):
super(FirstPage, self).__init__(parent)
self.setTitle("First page")
class SecondPage(QtWidgets.QWizardPage):
def __init__(self, parent=None):
super(SecondPage, self).__init__(parent)
self.setTitle("Second page")
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
main = Main()
main.show()
sys.exit(app.exec_())

Disable mouse pointer in QGraphicsView

I want to disable the mouse pointer in a QGraphicsView.
What line of code do I need to add in the following example?
import sys
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QApplication, QGraphicsView
class GraphicsWindow(QGraphicsView):
def __init__(self, parent=None):
super().__init__(parent)
self.showFullScreen()
def keyPressEvent(self, event):
if event.key() == Qt.Key_Escape:
self.close()
if __name__ == "__main__":
app = QApplication(sys.argv)
graphics_window = GraphicsWindow()
graphics_window.show()
sys.exit(app.exec_())
Qt::BlankCursor A blank/invisible cursor, typically used when the cursor shape needs to be hidden.
import sys
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QApplication, QGraphicsView
class GraphicsWindow(QGraphicsView):
def __init__(self, parent=None):
super().__init__(parent)
self.showFullScreen()
self.setCursor(Qt.BlankCursor) # < ------
def keyPressEvent(self, event):
if event.key() == Qt.Key_Escape:
self.close()
if __name__ == "__main__":
app = QApplication(sys.argv)
graphics_window = GraphicsWindow()
graphics_window.show()
sys.exit(app.exec_())

Resources