pyqt qtabwidget horizontal tab and horizontal text in QtDesigner - python

i am having problem to change text alignment using pyqt4 desginer i have made tabs horizontal by aligning west but the text in that goes north to south that looks bad i want to change alignment of text as horizontal how can i do that...thanks in advance.
this is my ui.py code
# Form implementation generated from reading ui file 'untitled.ui'
#
# Created by: PyQt4 UI code generator 4.11.4
#
# WARNING! All changes made in this file will be lost!
from PyQt4 import QtCore, QtGui
try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
def _fromUtf8(s):
return s
try:
_encoding = QtGui.QApplication.UnicodeUTF8
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig)
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName(_fromUtf8("MainWindow"))
MainWindow.resize(800, 600)
self.centralwidget = QtGui.QWidget(MainWindow)
self.centralwidget.setObjectName(_fromUtf8("centralwidget"))
self.gridLayout = QtGui.QGridLayout(self.centralwidget)
self.gridLayout.setObjectName(_fromUtf8("gridLayout"))
self.tabWidget = QtGui.QTabWidget(self.centralwidget)
self.tabWidget.setTabPosition(QtGui.QTabWidget.West)
self.tabWidget.setObjectName(_fromUtf8("tabWidget"))
self.tab = QtGui.QWidget()
self.tab.setObjectName(_fromUtf8("tab"))
self.tabWidget.addTab(self.tab, _fromUtf8(""))
self.tab_2 = QtGui.QWidget()
self.tab_2.setObjectName(_fromUtf8("tab_2"))
self.tabWidget.addTab(self.tab_2, _fromUtf8(""))
self.tab_3 = QtGui.QWidget()
self.tab_3.setObjectName(_fromUtf8("tab_3"))
self.tabWidget.addTab(self.tab_3, _fromUtf8(""))
self.gridLayout.addWidget(self.tabWidget, 0, 0, 1, 1)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtGui.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 31))
self.menubar.setObjectName(_fromUtf8("menubar"))
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtGui.QStatusBar(MainWindow)
self.statusbar.setObjectName(_fromUtf8("statusbar"))
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
self.tabWidget.setCurrentIndex(0)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow", None))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab), _translate("MainWindow", "Tab 1", None))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_2), _translate("MainWindow", "Tab 2", None))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_3), _translate("MainWindow", "Page", None))
if __name__ == "__main__":
import sys
app = QtGui.QApplication(sys.argv)
MainWindow = QtGui.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
and this is my main file where i ll add all the functions and from here i generate my window
from untitled import *
from PyQt4 import QtGui # Import the PyQt4 module we'll need
import sys # We need sys so that we can pass argv to QApplication
import os
from PyQt4.QtGui import *
from PyQt4.QtCore import *
class MainWindow(QMainWindow,Ui_MainWindow):
def __init__(self, parent=None):
QMainWindow.__init__(self, parent)
self.setupUi(self)
if __name__ == '__main__':
app = QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())

The solution that I propose may not be the exact solution but I think it is the one that comes closest. What I propose is to promote the QTabWidget to use a custom QTabWidget.
Before that I have improved the solution proposed in this answer:
tabwidget.py
from PyQt4 import QtGui, QtCore
class HorizontalTabBar(QtGui.QTabBar):
def paintEvent(self, event):
painter = QtGui.QStylePainter(self)
option = QtGui.QStyleOptionTab()
for index in range(self.count()):
self.initStyleOption(option, index)
painter.drawControl(QtGui.QStyle.CE_TabBarTabShape, option)
painter.drawText(self.tabRect(index),
QtCore.Qt.AlignCenter | QtCore.Qt.TextDontClip,
self.tabText(index))
def tabSizeHint(self, index):
size = QtGui.QTabBar.tabSizeHint(self, index)
if size.width() < size.height():
size.transpose()
return size
class TabWidget(QtGui.QTabWidget):
def __init__(self, parent=None):
QtGui.QTabWidget.__init__(self, parent)
self.setTabBar(HorizontalTabBar())
This file will be stored next to the .ui file and the .py files as shown in the following structure:
.
├── main.py # file of class MainWindow(QMainWindow,Ui_MainWindow):
├── tabwidget.py # custom QTabWidget
├── untitled.py
└── untitled.ui # your design
After having the previous structure we open the .ui file with Qt Designer and we right click on the QTabWidget and select promoted to ...:
A dialogue will open and the following should be placed in it:
Then press the add button and then the promote button, and at the end you generate the .py file again with the help of pyuic
At the end you get the following widget:

I know this has been awhile but if anyone needs #Sahil Jain's answer in PyQt5 version, please refer to following for your tabwidget.py
from PyQt5 import QtGui, QtCore, QtWidgets
class HorizontalTabBar(QtWidgets.QTabBar):
def paintEvent(self, event):
painter = QtWidgets.QStylePainter(self)
option = QtWidgets.QStyleOptionTab()
for index in range(self.count()):
self.initStyleOption(option, index)
painter.drawControl(QtWidgets.QStyle.CE_TabBarTabShape, option)
painter.drawText(self.tabRect(index),
QtCore.Qt.AlignCenter | QtCore.Qt.TextDontClip,
self.tabText(index))
def tabSizeHint(self, index):
size = QtWidgets.QTabBar.tabSizeHint(self, index)
if size.width() < size.height():
size.transpose()
return size
class TabWidget(QtWidgets.QTabWidget):
def __init__(self, parent=None):
QtWidgets.QTabWidget.__init__(self, parent)
self.setTabBar(HorizontalTabBar())

Using the above method and after that adding a line of code to it and got my icons displayed
from PyQt4 import QtGui, QtCore
class HorizontalTabBar(QtGui.QTabBar):
def paintEvent(self, event):
painter = QtGui.QStylePainter(self)
option = QtGui.QStyleOptionTab()
for index in range(self.count()):
self.initStyleOption(option, index)
painter.drawControl(QtGui.QStyle.CE_TabBarTabShape, option)
painter.drawText(self.tabRect(index),
QtCore.Qt.AlignCenter | QtCore.Qt.TextDontClip,
self.tabText(index))
if index == 0:
painter.drawImage(QtCore.QRectF(10, 10, 66, 67), QtGui.QImage("ico/HOME.png"))
def tabSizeHint(self, index):
size = QtGui.QTabBar.tabSizeHint(self, index)
size.setHeight=50
size.setWidth=200
if size.width() < size.height():
size.transpose()
return size
class TabWidget(QtGui.QTabWidget):
def __init__(self, parent=None):
QtGui.QTabWidget.__init__(self, parent)
self.setTabBar(HorizontalTabBar())
you can add icons as per the indexes of your tabs and set their position accordingly till now this is best solution i can give.cheers

Better way for looks and usability:
At the Qt Designer>
Use QToolBox at left side and QTabWidget at right.
Connect both with signal (currentChanged(int) - setCurrentIndex(int)).
Hide QTabWidget header with following css.
QTabBar::tab {height: 0px;}
Here an Example:

Related

Pyqt5: dyamically add a table to a tab

In my main program, I have a Dock widget (Vertical layout) containing a TabWidget (layouts added per tab). In my first tab I have added a static table, which resizes with the dock.
I am trying to allow the user to dynamically add a tab by importing a TableWidget design from another file into a tab; however, I am having trouble getting the layout to mimic the first tab.
Below is my code. I can make the table appear in the freshly made tab, just not fully adjust to the dock window.
My python start file:
from PyQt5 import QtCore, QtWidgets, QtGui
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
import mainwindow, sys, os, PyQt5, resources, dataTable
class dataForm(QtWidgets.QWidget, dataTable.Ui_Form)
def __init__(self, parent=None):
super(dataForm, self).__init__(parent)
self.setupUi(self)
class Example(QtWidgets.QMainWindow, mainwindow.Ui_MainWindow):
def __init__(self, parent=None):
super(Example, self).__init__(parent)
self.setupUi(self)
self.shortcut.activated.connect(self.addTabs)
def Resolution(self):
app = QtWidgets.QApplication([])
resolution = app.desktop().screenGeometry()
width, height = resolution.width(), resolution.height()
self.setMaximumSize(QtCore.QSize(width, height))
def addTabs(self):
self.DataSets.setUpdatesEnabled(True)
self.tab = QtWidgets.QWidget()
self.tab.setAutoFillBackground(False)
self.tab.setObjectName("userAdded")
pages = self.count()
# Set the tab layout
self.tableLayout = QtWidgets.QVBoxLayout(self.tab)
self.tableLayout.setContentsMargins(1, 0, 1, 0)
self.tableLayout.setSpacing(0)
self.tableLayout.setObjectName("tableGrid")
# Add table to the new tab widget
self.table = dataForm(self.tab)
# Add table to layout
self.tableLayout.addWidget(self.table)
self.tableLayout.addStretch()
# Add the tab and go to that location
self.DataSets.insertTab((pages-1), self.tab, "Set %d" %(pages))
self.DataSets.setCurrentIndex(pages-1)
def main():
app = QtWidgets.QApplication(sys.argv)
form = Example()
form.showMaximized()
app.exec_()
if __name__ == '__main__':
main()
and my dataTable.ui form:
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_Form(object):
def setupUi(self, Form):
Form.setObjectName("Form")
Form.resize(242, 450)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(Form.sizePolicy().hasHeightForWidth())
Form.setSizePolicy(sizePolicy)
self.tableWidget = QtWidgets.QTableWidget(Form)
self.tableWidget.setGeometry(QtCore.QRect(1, 0, 240, 450))
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.tableWidget.sizePolicy().hasHeightForWidth())
self.tableWidget.setSizePolicy(sizePolicy)
self.tableWidget.setContextMenuPolicy(QtCore.Qt.DefaultContextMenu)
self.tableWidget.setAutoFillBackground(True)
self.tableWidget.setStyleSheet("QHeaderView::section { background-color:rgb(140, 200, 172)};\n"
"")
self.tableWidget.setFrameShape(QtWidgets.QFrame.Panel)
self.tableWidget.setFrameShadow(QtWidgets.QFrame.Plain)
self.tableWidget.setSizeAdjustPolicy(QtWidgets.QAbstractScrollArea.AdjustToContentsOnFirstShow)
self.tableWidget.setDragEnabled(True)
self.tableWidget.setAlternatingRowColors(True)
self.tableWidget.setGridStyle(QtCore.Qt.SolidLine)
self.tableWidget.setRowCount(35)
self.tableWidget.setColumnCount(10)
self.tableWidget.setObjectName("tableWidget")
item = QtWidgets.QTableWidgetItem()
brush = QtGui.QBrush(QtGui.QColor(50, 0, 0))
brush.setStyle(QtCore.Qt.NoBrush)
item.setForeground(brush)
self.tableWidget.setItem(0, 1, item)
self.tableWidget.horizontalHeader().setCascadingSectionResizes(False)
self.tableWidget.horizontalHeader().setDefaultSectionSize(70)
self.tableWidget.horizontalHeader().setHighlightSections(True)
self.tableWidget.horizontalHeader().setMinimumSectionSize(39)
self.tableWidget.verticalHeader().setVisible(True)
self.tableWidget.verticalHeader().setDefaultSectionSize(20)
self.tableWidget.verticalHeader().setSortIndicatorShown(True)
self.tableWidget.verticalHeader().setStretchLastSection(False)
self.retranslateUi(Form)
QtCore.QMetaObject.connectSlotsByName(Form)
def retranslateUi(self, Form):
_translate = QtCore.QCoreApplication.translate
Form.setWindowTitle(_translate("Form", "Form"))
self.tableWidget.setSortingEnabled(True)
__sortingEnabled = self.tableWidget.isSortingEnabled()
self.tableWidget.setSortingEnabled(False)
self.tableWidget.setSortingEnabled(__sortingEnabled)
I'm pretty close, I think. Any suggestions?
Edit: Updated code to make the dataTable classified as a QWidget & passed self.tab as its parent in def AddTabs. Also, I added a part of the layout of AddTabs that was cut out accidentally.

Stdout stops showing in QTextEdit once another window has opened

I am trying to get stdout and error messages to show on my main window. The window is by pyqt and made via designer. I have a QTextEdit on it. This is where the output should show itself. Also I have a dialog box (again made via designer) where i set some settings for my program before running it. The dialog box is opened like this:
def open_settings(self):
dialog = SettingsDialog()
dialog.open_settings_tab() # its on a tab widget
I already read and used the info on these links to achieve my goal:
Print out python console output to Qtextedit
How to capture output of Python's interpreter and show in a Text widget?
Both are pretty much the same with different object names. The issue I'm having is that whenever I open a dialog box and return to the main window the stdout no longer shows itself on the QTextEdit. Instead it goes back to showing itself on Sublime Editor.
I believe it has something to do with the class instancing.
Here is how the Dialog class starts:
class SettingsDialog(QDialog):
def __init__(self, parent=None):
super(SettingsDialog, self).__init__(parent)
self.ui = Ui_SettingsDialog()
self.ui.setupUi(self)
and finally here is how my main window (form) class starts:
class MyForm(QMainWindow):
def __init__(self, parent=None):
super(MyForm, self).__init__(parent)
# Install the custom output stream
sys.stdout = EmittingStream(textWritten=self.normalOutputWritten)
self.ui = Ui_MyForm()
self.ui.setupUi(self)
Any ideas of why the stdout stops working (in qtextedit) once i go into the dialog screen and come back?
NEW Update:
The code is very long. I made a small program thats showing the issue:
PS: I found that the problem is related with this line shown below:
self.ui.pushButton_path.clicked.connect(Form(self).change_path)
if i comment it out the problem goes away.. But I need to call that function (which opens a QDialog, from the main form). What is the proper way?
main:
import sys
from PyQt5.QtWidgets import QApplication, QMainWindow, QDialog
from PyQt5.QtCore import QObject, pyqtSignal
from PyQt5.QtGui import QTextCursor
from ui_form import Ui_Form
from ui_dialog import Ui_Dialog
class EmittingStream(QObject): # test
textWritten = pyqtSignal(str)
def write(self, text):
self.textWritten.emit(str(text))
class Form(QMainWindow):
def __init__(self, parent=None):
super(Form, self).__init__(parent)
# Install the custom output stream
sys.stdout = EmittingStream(textWritten=self.normalOutputWritten) # test
self.ui = Ui_Form()
self.ui.setupUi(self)
self.ui.pushButton_open.clicked.connect(self.open_dialog)
self.ui.pushButton_text.clicked.connect(self.test_write)
def __del__(self): # test
# Restore sys.stdout
sys.stdout = sys.__stdout__
def normalOutputWritten(self, text): # test
"""Append text to the QTextEdit."""
# Maybe QTextEdit.append() works as well, but this is how I do it:
# self.ui.tEdit_cli.insertPlainText(text)
cursor = self.ui.textEdit.textCursor()
cursor.movePosition(QTextCursor.End)
cursor.insertText(text)
self.ui.textEdit.setTextCursor(cursor)
self.ui.textEdit.ensureCursorVisible()
def open_dialog(self):
dialog = Dialog()
dialog.open_tab()
def test_write(self):
print("something written")
def change_path(self):
pass
class Dialog(QDialog):
def __init__(self, parent=None):
super(Dialog, self).__init__(parent)
self.ui = Ui_Dialog()
self.ui.setupUi(self)
self.ui.pushButton_close.clicked.connect(self.close_dialog)
self.ui.pushButton_path.clicked.connect(Form(self).change_path) # this is what causes the issue. but i need to use it!
def open_tab(self):
self.ui.tabWidget.setCurrentIndex(0)
self.exec_()
def close_dialog(self):
self.close()
def main():
app = QApplication(sys.argv)
form = Form()
form.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
ui_dialog:
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'dialog.ui'
#
# Created by: PyQt5 UI code generator 5.6
#
# WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_Dialog(object):
def setupUi(self, Dialog):
Dialog.setObjectName("Dialog")
Dialog.resize(400, 300)
self.horizontalLayout = QtWidgets.QHBoxLayout(Dialog)
self.horizontalLayout.setObjectName("horizontalLayout")
self.tabWidget = QtWidgets.QTabWidget(Dialog)
self.tabWidget.setObjectName("tabWidget")
self.tab = QtWidgets.QWidget()
self.tab.setObjectName("tab")
self.pushButton_close = QtWidgets.QPushButton(self.tab)
self.pushButton_close.setGeometry(QtCore.QRect(100, 80, 211, 131))
self.pushButton_close.setObjectName("pushButton_close")
self.pushButton_path = QtWidgets.QPushButton(self.tab)
self.pushButton_path.setGeometry(QtCore.QRect(30, 30, 75, 23))
self.pushButton_path.setObjectName("pushButton_path")
self.tabWidget.addTab(self.tab, "")
self.tab_2 = QtWidgets.QWidget()
self.tab_2.setObjectName("tab_2")
self.tabWidget.addTab(self.tab_2, "")
self.horizontalLayout.addWidget(self.tabWidget)
self.retranslateUi(Dialog)
QtCore.QMetaObject.connectSlotsByName(Dialog)
def retranslateUi(self, Dialog):
_translate = QtCore.QCoreApplication.translate
Dialog.setWindowTitle(_translate("Dialog", "Dialog"))
self.pushButton_close.setText(_translate("Dialog", "close"))
self.pushButton_path.setText(_translate("Dialog", "path"))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab), _translate("Dialog", "Tab 1"))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_2), _translate("Dialog", "Tab 2"))
"""
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_())
"""
ui_form:
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'form.ui'
#
# Created by: PyQt5 UI code generator 5.6
#
# WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_Form(object):
def setupUi(self, Form):
Form.setObjectName("Form")
Form.resize(800, 600)
self.centralwidget = QtWidgets.QWidget(Form)
self.centralwidget.setObjectName("centralwidget")
self.textEdit = QtWidgets.QTextEdit(self.centralwidget)
self.textEdit.setGeometry(QtCore.QRect(90, 230, 601, 271))
self.textEdit.setObjectName("textEdit")
self.pushButton_open = QtWidgets.QPushButton(self.centralwidget)
self.pushButton_open.setGeometry(QtCore.QRect(140, 80, 241, 81))
self.pushButton_open.setObjectName("pushButton_open")
self.pushButton_text = QtWidgets.QPushButton(self.centralwidget)
self.pushButton_text.setGeometry(QtCore.QRect(440, 80, 251, 81))
self.pushButton_text.setObjectName("pushButton_text")
Form.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(Form)
self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 21))
self.menubar.setObjectName("menubar")
Form.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(Form)
self.statusbar.setObjectName("statusbar")
Form.setStatusBar(self.statusbar)
self.retranslateUi(Form)
QtCore.QMetaObject.connectSlotsByName(Form)
def retranslateUi(self, Form):
_translate = QtCore.QCoreApplication.translate
Form.setWindowTitle(_translate("Form", "MainWindow"))
self.pushButton_open.setText(_translate("Form", "open dialog"))
self.pushButton_text.setText(_translate("Form", "write somthing"))
"""
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
Form = QtWidgets.QMainWindow()
ui = Ui_Form()
ui.setupUi(Form)
Form.show()
sys.exit(app.exec_())
"""
You must use the object to invoke a method, you must not use the class, so the instruction Form(self) is not valid.
You must make the connection where you can access the signal and the slot simultaneously, for example open_dialog would be a good place:
class Form(QMainWindow):
...
def open_dialog(self):
dialog = Dialog(self)
dialog.ui.pushButton_path.clicked.connect(self.change_path) # +++
dialog.open_tab()
def test_write(self):
print("something written")
def change_path(self):
pass
class Dialog(QDialog):
def __init__(self, parent=None):
super(Dialog, self).__init__(parent)
self.ui = Ui_Dialog()
self.ui.setupUi(self)
self.ui.pushButton_close.clicked.connect(self.close_dialog)
# self.ui.pushButton_path.clicked.connect(Form(self).change_path) ---
...

PyQt: Can't access inherited verticalLayout - "object has no attribute"

I've created a MainWindow design called Ui_Dashboard within Qt Designer. I've also created a widget called "units_table", which I'd like to import and display within the Ui_Dashboard.
I've created a new class and inherited the Ui_Dashboard class, but for some reason cannot access the verticalLayout object. See code below:
dashboard.py
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'dashboard.ui'
#
# Created by: PyQt4 UI code generator 4.11.4
#
# WARNING! All changes made in this file will be lost!
from PyQt4 import QtCore, QtGui
try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
def _fromUtf8(s):
return s
try:
_encoding = QtGui.QApplication.UnicodeUTF8
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig)
class Ui_Dashboard(object):
def setupUi(self, Dashboard):
Dashboard.setObjectName(_fromUtf8("Dashboard"))
Dashboard.resize(800, 600)
self.centralwidget = QtGui.QWidget(Dashboard)
self.centralwidget.setObjectName(_fromUtf8("centralwidget"))
self.widget = QtGui.QWidget(self.centralwidget)
self.widget.setGeometry(QtCore.QRect(50, 21, 683, 360))
self.widget.setObjectName(_fromUtf8("widget"))
self.verticalLayout = QtGui.QVBoxLayout(self.widget)
self.verticalLayout.setObjectName(_fromUtf8("verticalLayout"))
self.horizontalLayout = QtGui.QHBoxLayout()
self.horizontalLayout.setObjectName(_fromUtf8("horizontalLayout"))
self.units_button = QtGui.QPushButton(self.widget)
self.units_button.setCheckable(True)
self.units_button.setChecked(False)
self.units_button.setObjectName(_fromUtf8("units_button"))
self.horizontalLayout.addWidget(self.units_button)
self.calls_button = QtGui.QPushButton(self.widget)
self.calls_button.setCheckable(True)
self.calls_button.setObjectName(_fromUtf8("calls_button"))
self.horizontalLayout.addWidget(self.calls_button)
self.vehicles_button = QtGui.QPushButton(self.widget)
self.vehicles_button.setCheckable(True)
self.vehicles_button.setObjectName(_fromUtf8("vehicles_button"))
self.horizontalLayout.addWidget(self.vehicles_button)
self.persons_button = QtGui.QPushButton(self.widget)
self.persons_button.setCheckable(True)
self.persons_button.setObjectName(_fromUtf8("persons_button"))
self.horizontalLayout.addWidget(self.persons_button)
self.pushButton_6 = QtGui.QPushButton(self.widget)
self.pushButton_6.setCheckable(True)
self.pushButton_6.setObjectName(_fromUtf8("pushButton_6"))
self.horizontalLayout.addWidget(self.pushButton_6)
self.pushButton_4 = QtGui.QPushButton(self.widget)
self.pushButton_4.setCheckable(True)
self.pushButton_4.setObjectName(_fromUtf8("pushButton_4"))
self.horizontalLayout.addWidget(self.pushButton_4)
self.pushButton_5 = QtGui.QPushButton(self.widget)
self.pushButton_5.setCheckable(True)
self.pushButton_5.setObjectName(_fromUtf8("pushButton_5"))
self.horizontalLayout.addWidget(self.pushButton_5)
self.verticalLayout.addLayout(self.horizontalLayout)
self.inserted_module = QtGui.QWidget(self.widget)
self.inserted_module.setMinimumSize(QtCore.QSize(481, 321))
self.inserted_module.setObjectName(_fromUtf8("inserted_module"))
self.verticalLayout.addWidget(self.inserted_module)
Dashboard.setCentralWidget(self.centralwidget)
self.menubar = QtGui.QMenuBar(Dashboard)
self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 23))
self.menubar.setObjectName(_fromUtf8("menubar"))
Dashboard.setMenuBar(self.menubar)
self.statusbar = QtGui.QStatusBar(Dashboard)
self.statusbar.setObjectName(_fromUtf8("statusbar"))
Dashboard.setStatusBar(self.statusbar)
self.retranslateUi(Dashboard)
QtCore.QMetaObject.connectSlotsByName(Dashboard)
def retranslateUi(self, Dashboard):
Dashboard.setWindowTitle(_translate("Dashboard", "MainWindow", None))
self.units_button.setText(_translate("Dashboard", "Units", None))
self.calls_button.setText(_translate("Dashboard", "Calls", None))
self.vehicles_button.setText(_translate("Dashboard", "Vehicles", None))
self.persons_button.setText(_translate("Dashboard", "Persons", None))
self.pushButton_6.setText(_translate("Dashboard", "PushButton", None))
self.pushButton_4.setText(_translate("Dashboard", "PushButton", None))
self.pushButton_5.setText(_translate("Dashboard", "PushButton", None))
main.py
import sys
from PyQt4 import QtCore, QtGui, uic
from dashboard import Ui_Dashboard
class MainWindow(QtGui.QMainWindow, Ui_Dashboard):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.units_table = uic.loadUi('units_table.ui', self)
self.inserted_module = self.units_table
self.inserted_module.setMinimumSize(QtCore.QSize(481, 321))
self.verticalLayout.addWidget(self.inserted_module)
self.setupUi(self)
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec_()
I'm able to display the imported widget perfectly fine, but I need to add it as a child to the vertical layout, which is where I'm having difficulties. Despite Ui_Dashboard being inherited, I still can't access the verticalLayout.
I keep getting the following error:
AttributeError: 'MainWindow' object has no attribute 'verticalLayout'
verticalLayout does not exist because it is created in the setupUi() method, what you must do is load it before you want to use it. Another mistake is that you should not pass self to loadUi(), since what you will do is reimplement the widget's design:
import sys
from PyQt4 import QtCore, QtGui, uic
from dashboard import Ui_Dashboard
class MainWindow(QtGui.QMainWindow, Ui_Dashboard):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.setupUi(self)
self.units_table = uic.loadUi('units_table.ui')
self.verticalLayout.addWidget(self.units_table )
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())

The Code does not work successfully when the function is called

I want to call method (close_ok()) in (main.py ) from method :close_call() in (module_b.py), but the Code does not work successfully when the function is called.
can anyone help me with this problem?
Here's the code for that :
###main.py
# -*- coding: utf-8 -*-
from PyQt4 import QtCore, QtGui
import sys
from GUI import Ui_MainWindow
class MainWindow(QtGui.QMainWindow,Ui_MainWindow):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
from module_c import class_c
global b
b=class_c()
QtCore.QObject.connect(self.ui.pushButton, QtCore.SIGNAL("clicked()"), b.close_call )
def close_ok(self):
##But it can not be done successfully.
self.close()
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
global myapp
myapp = MainWindow()
myapp.show()
sys.exit(app.exec_())
### module_b.py
class class_c (object):
def __init__(self, parent=None):
self.parent=parent
### I want call method (close_ok()) in (menu class) from here
def close_call (self):
from main import MainWindow
t=MainWindow()
t.close_ok()
###GUIpy
# -*- coding: utf-8 -*-
from PyQt4 import QtCore, QtGui
try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
def _fromUtf8(s):
return s
try:
_encoding = QtGui.QApplication.UnicodeUTF8
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig)
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
super(Ui_MainWindow, self).__init__()
MainWindow.setObjectName(_fromUtf8("MainWindow"))
MainWindow.resize(800, 600)
self.centralwidget = QtGui.QWidget(MainWindow)
self.centralwidget.setObjectName(_fromUtf8("centralwidget"))
self.pushButton = QtGui.QPushButton(self.centralwidget)
self.pushButton.setGeometry(QtCore.QRect(340, 110, 75, 23))
self.pushButton.setObjectName(_fromUtf8("pushButton"))
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtGui.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 21))
self.menubar.setObjectName(_fromUtf8("menubar"))
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtGui.QStatusBar(MainWindow)
self.statusbar.setObjectName(_fromUtf8("statusbar"))
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow", None))
self.pushButton.setText(_translate("MainWindow", "PushButton", None))
you use diffrent instances of the class MainWindow() so it wont close the original window, change it like this:
class MainWindow(QtGui.QMainWindow,Ui_MainWindow):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
from module_c import class_c
global b
b=class_c(self) #NOTICE THE CHANGE HERE
QtCore.QObject.connect(self.ui.pushButton, QtCore.SIGNAL("clicked()"), b.close_call )
def close_ok(self):
self.close()
and change module b to do:
class class_c (object):
def __init__(self, parent=None):
self.parent=parent
def close_call (self):
from main import MainWindow
self.parent.close_ok()# NOTICE THIS CHANGE, parent is now the original MainWindow
this way you pass your original MainWindow instancce to class_c and use it, instead of creating a new instance

pyqt: How to dynamically update widget property on outer variable value change?

I have class Ui_MainWindow(object) that creates a window with a progress bar and class OtherClass(object) that contains method in which the local int variable increments in cycle.
How to connect local variable value change to progres bar value change?
mainGUI.py
import sys
from PyQt4.uic.Compiler.qtproxies import QtGui
from PyQt4 import QtGui
from Ui_MainWindow import Ui_MainWindow
def main():
app = QtGui.QApplication(sys.argv)
MainWindow = QtGui.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
Ui_MainWindow.py
from PyQt4 import QtCore, QtGui
from MainGui.OtherClass import OtherClass
try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
_fromUtf8 = lambda s: s
class Ui_MainWindow(object):
def myButtonSlot(self):
objVar=OtherClass()
objVar.method()
def setupUi(self, MainWindow):
MainWindow.setObjectName(_fromUtf8("MainWindow"))
MainWindow.resize(389, 332)
self.centralwidget = QtGui.QWidget(MainWindow)
self.centralwidget.setObjectName(_fromUtf8("centralwidget"))
self.verticalLayout = QtGui.QVBoxLayout(self.centralwidget)
self.verticalLayout.setObjectName(_fromUtf8("verticalLayout"))
self.pushButton = QtGui.QPushButton(self.centralwidget)
self.pushButton.setObjectName(_fromUtf8("pushButton"))
self.pushButton.clicked.connect(self.myButtonSlot)
self.verticalLayout.addWidget(self.pushButton)
self.progressBar = QtGui.QProgressBar(self.centralwidget)
self.progressBar.setProperty("value", 24)
self.progressBar.setObjectName(_fromUtf8("progressBar"))
self.verticalLayout.addWidget(self.progressBar)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtGui.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 389, 21))
self.menubar.setObjectName(_fromUtf8("menubar"))
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtGui.QStatusBar(MainWindow)
self.statusbar.setObjectName(_fromUtf8("statusbar"))
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
MainWindow.setWindowTitle(QtGui.QApplication.translate("MainWindow", "MainWindow", None, QtGui.QApplication.UnicodeUTF8))
self.pushButton.setText(QtGui.QApplication.translate("MainWindow", "PushButton", None, QtGui.QApplication.UnicodeUTF8))
OtherClass.py
class OtherClass(object):
def method(self):
for i in range(100): # i want to connect variable i to progress bar value
print i
for j in range(100500):
pass
You need to re-organize your code a little bit.
Firstly, you should never edit the code in the UI module generated by pyuic. Instead, import it into your main module and implement all your application logic there.
Secondly, you should create a main-window class in your main module, and do all the setup inside its __init__ method.
One way to solve your problem of connecting the loop variable to the progress bar, is to make OtherClass a subclass of QObject and emit a custom signal:
from PyQt4 import QtCore
class OtherClass(QtCore.QObject):
valueUpdated = QtCore.pyqtSignal(int)
def method(self):
# i want to connect variable i to progress bar value
for i in range(100):
print i
self.valueUpdated.emit(i)
for j in range(100500):
pass
With that in place, you would then move the setup for pushButton and its slot to "mainGUI.py", and re-generate "Ui_MainWindow.py" with pyuic. A slot would then be added to handle the custom valueChanged signal, which would update the progress bar and also process any pending GUI events.
So "mainGUI.py" would end up looking something like this:
import sys
from PyQt4 import QtGui
from Ui_MainWindow import Ui_MainWindow
from OtherClass import OtherClass
class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
def __init__(self):
QtGui.QMainWindow.__init__(self)
self.setupUi(self)
self.pushButton.clicked.connect(self.myButtonSlot)
self.otherclass = OtherClass(self)
self.otherclass.valueUpdated.connect(self.handleValueUpdated)
def myButtonSlot(self):
self.otherclass.method()
def handleValueUpdated(self, value):
self.progressBar.setValue(value)
QtGui.qApp.processEvents()
def main():
app = QtGui.QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
The following post has a version that increments the progress bar 10% each time you press the button. And a version which uses a timer to increment the progress bar. (I'm just in the process of learning this myself)
In Qt Designer, add a progress bar and a button. Click on 'Edit Signals/Slots', drag a line from the button to somewhere in the window and when the button is 'pressed()' add a slot(or signal??) called 'button_pressed()' (use the + button to make this). When you have done this, the OK button is greyed out - select the slot you made, and press OK.
Save the file as ui_MainWindow.ui (note the capitals carefully).
Convert to a py file using the batch file >
pyuic4 -x ui_MainWindow.ui -o ui_MainWindow.py
This file should look something like....(you don't need to edit this).
from PyQt4 import QtCore, QtGui
try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
def _fromUtf8(s):
return s
try:
_encoding = QtGui.QApplication.UnicodeUTF8
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig)
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName(_fromUtf8("MainWindow"))
MainWindow.resize(800, 600)
self.centralwidget = QtGui.QWidget(MainWindow)
self.centralwidget.setObjectName(_fromUtf8("centralwidget"))
self.progressBar = QtGui.QProgressBar(self.centralwidget)
self.progressBar.setGeometry(QtCore.QRect(110, 90, 118, 23))
self.progressBar.setProperty("value", 24)
self.progressBar.setObjectName(_fromUtf8("progressBar"))
self.pushButton = QtGui.QPushButton(self.centralwidget)
self.pushButton.setGeometry(QtCore.QRect(120, 200, 75, 23))
self.pushButton.setObjectName(_fromUtf8("pushButton"))
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtGui.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 21))
self.menubar.setObjectName(_fromUtf8("menubar"))
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtGui.QStatusBar(MainWindow)
self.statusbar.setObjectName(_fromUtf8("statusbar"))
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QObject.connect(self.pushButton, QtCore.SIGNAL(_fromUtf8("pressed()")), MainWindow.button_pressed)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow", None))
self.pushButton.setText(_translate("MainWindow", "PushButton", None))
if __name__ == "__main__":
import sys
app = QtGui.QApplication(sys.argv)
MainWindow = QtGui.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
Create a 'program.py' file. This is the file you will run...
import sys
from PyQt4 import QtGui
#from PyQt5 import QtCore, QtGui, QtWidgets #works for pyqt5
from mainWindow import MainWindow
def main():
#app = QtWidgets.QApplication (sys.argv) #works for pyqt5
app = QtGui.QApplication (sys.argv) #works for pyqt4
m = MainWindow ()
m.show ()
sys.exit (app.exec_ () )
if __name__ == '__main__':
main ()
Now this is where the good stuff happens when you subclass the mainwindow. Call this file 'mainWindow.py'. Careful with the capitalizations.
from PyQt4 import QtCore, QtGui
from ui_MainWindow import Ui_MainWindow #note the capitalization
class MainWindow (QtGui.QMainWindow):
def __init__ (self, parent = None):
super (MainWindow, self).__init__ ()
self.ui = Ui_MainWindow ()
self.ui.setupUi (self)
#------------do your custom stuff from here on-----------
self.progress = 0 #Start value of progress bar
self.ui.progressBar.setValue(self.progress)
def button_pressed(self):
print('button pressed')
self.ui.statusbar.showMessage(str(self.progress)) #this is at bottom left of window. Discovered this accidentially when doing this!
self.ui.progressBar.setValue(self.progress)
self.progress+=10
There is a good tutorial here which I used to create an alternate 'mainWindow.py' which uses a timer to increment the progress bar. It does not block the code with a loop using sleep or by doing a CPU intensive loop. I don't understand multithreading, multi-processor options yet to comment on using these.
#from PyQt5 import QtCore, QtGui, QtWidgets #works for PyQt5
from PyQt4 import QtCore, QtGui
from ui_MainWindow import Ui_MainWindow #note the capitalization
class MainWindow (QtGui.QMainWindow):
def __init__ (self, parent = None):
super (MainWindow, self).__init__ ()
self.ui = Ui_MainWindow () #same name as appears in mainWindowUi.py
self.ui.setupUi (self)
self.progress = 0 #Start value of progress bar
self.ui.progressBar.setValue(self.progress)
self.timer = QtCore.QBasicTimer()
def button_pressed(self):
self.timerEvent(64) #this needs an argument to work but I'm not sure what is is yet so I just put in some random number
def timerEvent(self, e):
self.ui.progressBar.setValue(self.progress)
if self.progress >=100:
self.timer.stop()
else:
if self.timer.isActive():
pass
else:
self.timer.start(10,self) #10 milliseconds
self.progress+=1
You have to use a signal and slot...and multiprocessing or multithreading.
There's a good example here that specifically takes you through the progress bar:
ZetCode Progress Bar
Also, question has been answered here before:
SO Progress Bar

Categories