How to switch between tabs via pushbutton ? using pyqt - python-3.x

I am newbie and maybe this is silly question.
I want to activate tab by clicking on pushButton . If I click pushButton_1 then it shows/activates tab_1, on the clicking pushButton_2 switches to tab_2, and so on . Bellow there is pic how I tried it but without success. Help me solve this and write correct code down. Thank you in advance.
This is my code :
from spex import *
import sys
class speX (Ui_MainWindow):
def __init__(self, window):
self.setupUi(window)
self.systemButton.clicked.setCurrentIndex(self, 0)
self.cpuButton.clicked.setCurrentIndex(self, 1)
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = speX (MainWindow)
MainWindow.show()
app.exec_()
I want this - when I click systemButton, activate tab indexed as 0, when click cpuButton activate tab indexed as 1.
Error provided there -
Traceback (most recent call last):
File "d:\spex\main.py", line 17, in <module>
ui = speX (MainWindow)
File "d:\spex\main.py", line 9, in __init__
self.systemButton.clicked.setCurrentIndex(self, 0)
AttributeError: 'PyQt5.QtCore.pyqtBoundSignal' object has no attribute 'setCurrentIndex'
This is example of my project - pyuic5 ui to py code
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'D:/spex/example.ui'
#
# Created by: PyQt5 UI code generator 5.13.2
#
# WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(763, 611)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.stackedWidget = QtWidgets.QStackedWidget(self.centralwidget)
self.stackedWidget.setGeometry(QtCore.QRect(270, 70, 361, 361))
self.stackedWidget.setObjectName("stackedWidget")
self.page = QtWidgets.QWidget()
self.page.setObjectName("page")
self.buttonBox = QtWidgets.QDialogButtonBox(self.page)
self.buttonBox.setGeometry(QtCore.QRect(50, 310, 193, 28))
self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok)
self.buttonBox.setObjectName("buttonBox")
self.stackedWidget.addWidget(self.page)
self.page_2 = QtWidgets.QWidget()
self.page_2.setObjectName("page_2")
self.commandLinkButton = QtWidgets.QCommandLinkButton(self.page_2)
self.commandLinkButton.setGeometry(QtCore.QRect(70, 190, 222, 48))
self.commandLinkButton.setObjectName("commandLinkButton")
self.stackedWidget.addWidget(self.page_2)
self.pushButton = QtWidgets.QPushButton(self.centralwidget)
self.pushButton.setGeometry(QtCore.QRect(50, 110, 93, 28))
self.pushButton.setObjectName("pushButton")
self.pushButton_2 = QtWidgets.QPushButton(self.centralwidget)
self.pushButton_2.setGeometry(QtCore.QRect(50, 190, 93, 28))
self.pushButton_2.setObjectName("pushButton_2")
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 763, 26))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
self.stackedWidget.setCurrentIndex(0)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.commandLinkButton.setText(_translate("MainWindow", "CommandLinkButton"))
self.pushButton.setText(_translate("MainWindow", "PushButton"))
self.pushButton_2.setText(_translate("MainWindow", "PushButton"))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())

In Qt, a signal is emitted when a particular event occurs: a button is clicked, some text is changed, etc.
Signals are then connected to slots, which are functions that can react in some way to those signals. For example, you can create a slot that changes the text in a label, and connect it to a clicked signal of a button: then, when you click on that button, the text is changed.
Why your code does not work?
Well, for instance, setCurrentIndex is a method of a QStackedWidget (similarly to a QTabWidget), so the following doesn't make much sense:
self.systemButton.clicked.setCurrentIndex(self, 0)
Where is the reference to the stacked widget?
In PyQt, you can connect signals and slots like this:
someObject.signal.connect(someFunction)
Note that someFunction is a reference to that function; the following will not work:
someObject.signal.connect(someFunction())
If you want to change the index of a stacked widget after clicking on a button, you have to create a function that changes that index, and connect it to the clicked signal.
class speX (Ui_MainWindow):
def __init__(self, window):
self.setupUi(window)
self.pushButton.clicked.connect(self.goToSecondPage)
def goToSecondPage(self):
self.stackedWidget.setCurrentIndex(1)
I strongly suggest you to carefully study how python classes work and, generally speaking, the Object Oriented programming paradigm.

The simplist solution would be to connect your buttons to a function that changes the tab index on click
tabs = QtWidget.QTabWidget()
tab1 = QtWidget.QWidget()
tabs.addTab(self.tab1, "Tab 1")
systemButton.clicked.connect(tabIndex0)
def tabIndex0():
tabs.setCurrentIndex(0)

Related

PyQt5 calling gui from pyuic5 converted file or uic.loadUi

Hi I am new to python (up to lecture 2 and half of MIT 6001 Introduction to Computer Science and Programming in Python) nevetheless I started playing with Gtk & Glade and PyQt5 and Designer.
following https://stackoverflow.com/a/54081597/9877065 I used pyuic5 to convert my prova.ui, Designer generated window and imported in the code below:
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from prova1 import Ui_MainWindow
class MyWindow(QMainWindow):
def __init__(self):
super().__init__()
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
self.ButtonQ.clicked.connect(self.QPushButtonQPressed)
self.ButtonA.clicked.connect(self.QPushButtonAPressed)
def QPushButtonQPressed(self):
# This is executed when the button is pressed
print('pppppppp exit from QQQQQQQQQQQQQQQQQQQQQQQQQQQQQ')
sys.exit()
def QPushButtonAPressed(self):
# This is executed when the button is pressed
print('exit from AAAAAAAAAAAAAAAAAAAAAAA')
sys.exit()
if __name__ == '__main__':
app = QApplication(sys.argv)
w = MyWindow()
w.show()
sys.exit(app.exec_())
but when I run it in terminal I got a :
File "./main.py", line 80, in <module>
w = MyWindow()
File "./main.py", line 38, in __init__
self.ButtonQ.clicked.connect(self.QPushButtonQPressed)
AttributeError: 'MyWindow' object has no attribute 'ButtonQ'
error !!!!
while using loaduic like:
import sys
from PyQt5 import QtWidgets, uic
class Ui(QtWidgets.QMainWindow):
def __init__(self):
super(Ui, self).__init__()
uic.loadUi('prova1.ui', self)
self.ButtonQ.clicked.connect(self.QPushButtonQPressed)
self.ButtonA.clicked.connect(self.QPushButtonAPressed)
self.show()
def QPushButtonQPressed(self):
# This is executed when the button is pressed
print('pppppppp exit from QQQQQQQQQQQQQQQQQQQQQQQQQQQQQ')
sys.exit()
def QPushButtonAPressed(self):
# This is executed when the button is pressed
print('exit from AAAAAAAAAAAAAAAAAAAAAAA')
sys.exit()
app = QtWidgets.QApplication(sys.argv)
window = Ui()
app.exec_()
the program works as expected, that is show the window gui and exit if A or Quit button is pressed
as per the prova1.ui file that converted with pyuic5 gives, prova1.py:
# Form implementation generated from reading ui file 'prova1.ui'
#
# Created by: PyQt5 UI code generator 5.12.3
#
# WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(256, 351)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setEnabled(True)
self.centralwidget.setObjectName("centralwidget")
self.gridLayoutWidget = QtWidgets.QWidget(self.centralwidget)
self.gridLayoutWidget.setGeometry(QtCore.QRect(10, 0, 221, 261))
self.gridLayoutWidget.setObjectName("gridLayoutWidget")
self.gridLayout = QtWidgets.QGridLayout(self.gridLayoutWidget)
self.gridLayout.setContentsMargins(0, 0, 0, 0)
self.gridLayout.setObjectName("gridLayout")
self.ButtonA = QtWidgets.QPushButton(self.gridLayoutWidget)
font = QtGui.QFont()
font.setFamily("Abyssinica SIL")
font.setItalic(True)
font.setUnderline(True)
font.setStrikeOut(False)
font.setKerning(False)
self.ButtonA.setFont(font)
self.ButtonA.setCheckable(True)
self.ButtonA.setAutoDefault(False)
self.ButtonA.setDefault(False)
self.ButtonA.setObjectName("ButtonA")
self.gridLayout.addWidget(self.ButtonA, 0, 0, 1, 1)
self.C = QtWidgets.QPushButton(self.gridLayoutWidget)
self.C.setObjectName("C")
self.gridLayout.addWidget(self.C, 2, 0, 1, 1)
self.B = QtWidgets.QPushButton(self.gridLayoutWidget)
self.B.setObjectName("B")
self.gridLayout.addWidget(self.B, 1, 0, 1, 1)
self.ButtonQ = QtWidgets.QPushButton(self.gridLayoutWidget)
font = QtGui.QFont()
font.setBold(True)
font.setWeight(75)
self.ButtonQ.setFont(font)
self.ButtonQ.setCheckable(True)
self.ButtonQ.setAutoDefault(False)
self.ButtonQ.setDefault(False)
self.ButtonQ.setObjectName("ButtonQ")
self.gridLayout.addWidget(self.ButtonQ, 3, 0, 1, 1)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 256, 29))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
font = QtGui.QFont()
font.setBold(True)
font.setWeight(75)
self.statusbar.setFont(font)
self.statusbar.setAutoFillBackground(True)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.ButtonA.setText(_translate("MainWindow", "A"))
self.C.setText(_translate("MainWindow", "C"))
self.B.setText(_translate("MainWindow", "B"))
self.ButtonQ.setText(_translate("MainWindow", "Q quit"))
I am sure the error is somehow related to the class definitions but cannot really grasp it ? Any help ?
Heike solved it
In the first version of MyWindow, ButonA and ButtonQ are attributes of self.ui, not of self itself, so you need to use somthing like self.ui.ButtonA.clicked.connect(...), etc.

How to remove all widgets within a QGroupBox in PyQt5?

In my program there is a QGroupBox displayed that has many QPushButton's within it. During the execution of the program, the user can click a button outside of the QGroupBox and all of the buttons within it will be removed or hidden. Problem is that I can't seem to find a way to do this to the buttons directly or by clearing the QGroupBox.
I have already tried deleteLater on the buttons but that didn't work. I then tried clearing the layout of the QGroupBox but that didn't work either. Here is some code I just wrote up that has a the same problem:
from PyQt5 import QtCore, QtGui, QtWidgets
import sys
import random
class UI_Dialog(object):
def addButtons(self,looping):
# Code to remove the previous QPushButton's goes here.
placement = -100
for i in range(looping):
currentName = 'btn' + str(i)
placement = placement + 110
self.btnB = QtWidgets.QPushButton(self.groupBox)
self.btnB.setGeometry(QtCore.QRect(10+placement, 30+placement, 100, 100))
self.btnB.show()
self.btnB.setObjectName(currentName)
def setupUi(self, Dialog):
Dialog.setObjectName("Dialog")
Dialog.resize(1300, 800)
self.btnA = QtWidgets.QPushButton(Dialog)
self.btnA.setGeometry(QtCore.QRect(10, 80, 101, 131))
self.btnA.setObjectName("btn1")
self.btnA.clicked.connect(self.pushed)
self.formLayout = QtWidgets.QFormLayout()
self.groupBox = QtWidgets.QGroupBox("Results")
self.groupBox.setLayout(self.formLayout)
self.resultScrollArea = QtWidgets.QScrollArea(Dialog)
self.resultScrollArea.setWidget(self.groupBox)
self.resultScrollArea.setGeometry(QtCore.QRect(20, 220, 1011, 531))
self.resultScrollArea.setWidgetResizable(True)
self.resultScrollArea.setObjectName("resultScrollArea")
self.retranslateUi(Dialog)
QtCore.QMetaObject.connectSlotsByName(Dialog)
def pushed(self):
unkownLength = random.randint(1,20)
self.addButtons(unkownLength)
def retranslateUi(self, Dialog):
_translate = QtCore.QCoreApplication.translate
Dialog.setWindowTitle(_translate("Dialog", "Example Program"))
self.btnA.setText(_translate("Dialog", "Push Button"))
app = QtWidgets.QApplication(sys.argv)
Dialog = QtWidgets.QDialog()
ui = UI_Dialog()
ui.setupUi(Dialog)
Dialog.show()
sys.exit(app.exec_())
There are things here that probably don't make sense like the window size, the multiple function calls or it being a Dialog window instead of a QMainWindow. However, in the context of the actual program they do make sense so just ignore that, I know it's inefficient. Also the whole point of the unkownLength variable is to emulate that in the actual program, the number of buttons generated will be determined by user input. The buttons must also not be there at the start so that is why they're created with a button click. When the button is clicked again it should remove or hide all the buttons it created before. Any ideas?
Taking advantage that the buttons are children of the QGroupBox we can get the buttons using findChildren() to use deleteLater():
from PyQt5 import QtCore, QtGui, QtWidgets
import sys
import random
class UI_Dialog(object):
def setupUi(self, Dialog):
Dialog.setObjectName("Dialog")
Dialog.resize(1300, 800)
self.btnA = QtWidgets.QPushButton(Dialog)
self.btnA.setGeometry(QtCore.QRect(10, 80, 101, 131))
self.btnA.setObjectName("btn1")
self.formLayout = QtWidgets.QFormLayout()
self.groupBox = QtWidgets.QGroupBox("Results")
self.groupBox.setLayout(self.formLayout)
self.resultScrollArea = QtWidgets.QScrollArea(Dialog)
self.resultScrollArea.setWidget(self.groupBox)
self.resultScrollArea.setGeometry(QtCore.QRect(20, 220, 1011, 531))
self.resultScrollArea.setWidgetResizable(True)
self.resultScrollArea.setObjectName("resultScrollArea")
self.retranslateUi(Dialog)
QtCore.QMetaObject.connectSlotsByName(Dialog)
def retranslateUi(self, Dialog):
_translate = QtCore.QCoreApplication.translate
Dialog.setWindowTitle(_translate("Dialog", "Example Program"))
self.btnA.setText(_translate("Dialog", "Push Button"))
class Dialog(QtWidgets.QDialog, UI_Dialog):
def __init__(self, parent=None):
super(Dialog, self).__init__(parent)
self.setupUi(self)
self.btnA.clicked.connect(self.pushed)
#QtCore.pyqtSlot()
def pushed(self):
unkownLength = random.randint(1, 20)
self.addButtons(unkownLength)
def addButtons(self, looping):
for button in self.groupBox.findChildren(QtWidgets.QPushButton):
button.deleteLater()
placement = -100
pos = QtCore.QPoint(20, 40)
for i in range(looping):
currentName = "btn" + str(i)
self.btnB = QtWidgets.QPushButton(
self.groupBox, objectName=currentName
)
self.btnB.setGeometry(QtCore.QRect(pos, QtCore.QSize(100, 100)))
pos += QtCore.QPoint(110, 110)
self.btnB.show()
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
w = Dialog()
w.show()
sys.exit(app.exec_())

QLineEdit and keyPressEvent

I'm learning PyQt5 on python3 and I'm having some troubles with associating keyPressEvent to a QLineEdit.
I'd like to associate keyPressEvent to QLineEdit so that when I press a key having the LineEdit box selected an action is triggered.
Here an example of what I'd like to achieve:
I write something in the LineEdit Box
I press a key (say 'Enter' for example)
What I have wrote in the LineEdit Box is printed on the terminal
If I deselect the Box or select another object in my GUI (i.e. another LineEdit Box) and I press enter I don't trigger the previous action.
Here an example of the code where I'd like to implement this functionality:
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_Dialog(object):
def setupUi(self, Dialog):
Dialog.setObjectName("Dialog")
Dialog.resize(400, 300)
self.lineEdit = QtWidgets.QLineEdit(Dialog)
self.lineEdit.setGeometry(QtCore.QRect(90, 40, 113, 21))
self.lineEdit.setObjectName("lineEdit")
self.lineEdit_2 = QtWidgets.QLineEdit(Dialog)
self.lineEdit_2.setGeometry(QtCore.QRect(90, 80, 113, 21))
self.lineEdit_2.setObjectName("lineEdit_2")
self.retranslateUi(Dialog)
QtCore.QMetaObject.connectSlotsByName(Dialog)
def retranslateUi(self, Dialog):
_translate = QtCore.QCoreApplication.translate
Dialog.setWindowTitle(_translate("Dialog", "Dialog"))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
Dialog = QtWidgets.QDialog()
ui = Ui_Dialog()
ui.setupUi(Dialog)
Dialog.show()
sys.exit(app.exec_())
I hope someone can help me with this!

in PyQt5 move tab page widgets to desired tab page dynamically using tab index

In python, using PyQt5 while moving from one tab page to another, need to move the widgets from source page to destination tab page using the index number.
I was trying the following code. But No idea. Can anybody guide me. Thanks
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_Form(object):
def setupUi(self, Form):
Form.setObjectName("Form")
Form.resize(1251, 645)
self.tabWidget = QtWidgets.QTabWidget(Form)
self.tabWidget.setGeometry(QtCore.QRect(40, 40, 1161, 571))
self.tabWidget.setObjectName("tabWidget")
self.tab_1 = QtWidgets.QWidget()
self.tab_1.setObjectName("tab_1")
self.tabWidget.addTab(self.tab_1, "")
self.tab_2 = QtWidgets.QWidget()
self.tab_2.setObjectName("tab_2")
self.tabWidget.addTab(self.tab_2, "")
self.tabWidget.currentChanged.connect(self.header_Tab_Changed)
global TAB_OPTION
if TAB_OPTION==0:
self.pushButton = QtWidgets.QPushButton(self.tab_1)
self.pushButton.setGeometry(QtCore.QRect(290, 130, 631, 161))
self.pushButton.setObjectName("pushButton")
elif TAB_OPTION==1:
self.pushButton = QtWidgets.QPushButton(self.tab_2)
self.pushButton.setGeometry(QtCore.QRect(100, 100, 431, 61))
self.pushButton.setObjectName("pushButton")
self.retranslateUi(Form)
self.tabWidget.setCurrentIndex(0)
QtCore.QMetaObject.connectSlotsByName(Form)
def header_Tab_Changed(self,index):
global TAB_OPTION
TAB_OPTION=index
#I need to move the push button between tabs ????????????????
def retranslateUi(self, Form):
_translate = QtCore.QCoreApplication.translate
Form.setWindowTitle(_translate("Form", "Form"))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_1), _translate("Form", "First-Page"))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_2), _translate("Form", "Second-Page"))
self.pushButton.setText(_translate("Form", "PushButton"))
if __name__ == "__main__":
import sys
global TAB_OPTION
TAB_OPTION=0
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_Form()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())

How to Make a Button Perform Single Click Instead of Double Click

I'm experimenting on PyQt5. When I enter a value and click the push button to pass the value entered on my line edit, I noticed that it requires 2 mouse clicks for it to pass, and display the value on my plain text edit.
How will I change my codes to allow the entered value on the line edit to be passed by just 1 click?
from PyQt5 import QtCore, QtGui, QtWidgets
from functools import partial
class Ui_Form(object):
def setupUi(self, Form):
Form.setObjectName("Form")
Form.resize(640, 480)
self.label = QtWidgets.QLabel(Form)
self.label.setGeometry(QtCore.QRect(40, 80, 151, 31))
self.label.setObjectName("label")
self.lineEdit = QtWidgets.QLineEdit(Form)
self.lineEdit.setGeometry(QtCore.QRect(190, 90, 113, 20))
self.lineEdit.setObjectName("lineEdit")
self.label_2 = QtWidgets.QLabel(Form)
self.label_2.setGeometry(QtCore.QRect(40, 170, 181, 16))
self.label_2.setObjectName("label_2")
self.plainTextEdit = QtWidgets.QPlainTextEdit(Form)
self.plainTextEdit.setGeometry(QtCore.QRect(220, 170, 104, 71))
self.plainTextEdit.setReadOnly(True)
self.plainTextEdit.setObjectName("plainTextEdit")
self.pushButton = QtWidgets.QPushButton(Form)
self.pushButton.setGeometry(QtCore.QRect(310, 90, 75, 23))
self.pushButton.setObjectName("pushButton")
self.pushButton.clicked.connect(self.Pass)
self.retranslateUi(Form)
QtCore.QMetaObject.connectSlotsByName(Form)
def retranslateUi(self, Form):
_translate = QtCore.QCoreApplication.translate
Form.setWindowTitle(_translate("Form", "Form"))
self.label.setText(_translate("Form", "Pass the value entered here:"))
self.label_2.setText(_translate("Form", "Accept and display the passed value:"))
self.pushButton.setText(_translate("Form", "PASS"))
def Pass(self):
accept = self.lineEdit.text()
self.pushButton.clicked.connect(partial(self.Get, accept))
def Get(self, getA):
self.plainTextEdit.setPlainText(getA)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
Form = QtWidgets.QWidget()
ui = Ui_Form()
ui.setupUi(Form)
Form.show()
ui.Get(ui.Pass())
sys.exit(app.exec_())
.clicked fires the first time you click the button. The problem is however that you register Pass to the button:
self.pushButton.clicked.connect(self.Pass)
Now Pass is defined as:
def Pass(self):
accept = self.lineEdit.text()
# connect a new event
self.pushButton.clicked.connect(partial(self.Get, accept))
So the first time you click the button, you read the accept, and only connect the self.Get method to the button such that the next time you hit the button, self.Get will indeed be called.
In order to process the request straight away, you can simply modify the Pass method to:
def Pass(self):
accept = self.lineEdit.text()
self.Get(accept)

Resources