PyQt - Tabbed dialog not displaying embedded widgets - python

I am trying to create a dialog with three tabs using PyQt. However, I am annoyed because although the dialog is displayed, the embedded widgets are not displayed!. I suppose this is a very simple problem with a correspondingly very simple solution, but I am struck! Can anyone give a hint? Thanks in advance!
Here is my code so far:
import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
class TabbedDialog(QDialog):
def __init__(self, parent = None):
super(TabbedDialog, self).__init__(parent)
self.tabWidget = QTabWidget()
self.tabWidget.tab1 = QWidget()
self.tabWidget.tab2 = QWidget()
self.tabWidget.tab3 = QWidget()
self.tabWidget.addTab(self.tabWidget.tab1,"Tab 1")
self.tabWidget.addTab(self.tabWidget.tab2,"Tab 2")
self.tabWidget.addTab(self.tabWidget.tab3,"Tab 3")
self.tab1UI()
self.tab2UI()
self.tab3UI()
self.setWindowTitle("tab demo")
def tab1UI(self):
layout = QFormLayout()
layout.addRow("Name",QLineEdit())
layout.addRow("Address",QLineEdit())
self.tabWidget.setTabText(0,"Contact Details")
self.tabWidget.tab1.setLayout(layout)
def tab2UI(self):
layout = QFormLayout()
sex = QHBoxLayout()
sex.addWidget(QRadioButton("Male"))
sex.addWidget(QRadioButton("Female"))
layout.addRow(QLabel("Sex"),sex)
layout.addRow("Date of Birth",QLineEdit())
self.tabWidget.setTabText(1,"Personal Details")
self.tabWidget.tab2.setLayout(layout)
def tab3UI(self):
layout = QHBoxLayout()
layout.addWidget(QLabel("subjects"))
layout.addWidget(QCheckBox("Physics"))
layout.addWidget(QCheckBox("Maths"))
self.tabWidget.setTabText(2,"Education Details")
self.tabWidget.tab3.setLayout(layout)
if __name__ == '__main__':
app = QApplication(sys.argv)
form = TabbedDialog()
retval = form.exec_()

here is my solution to the problem
On the init method, I declared a layout, then added the 'tabWidget' widget to that layout and set that layout as the layout of your QDialog.
def __init__(self, parent = None):
super(TabbedDialog, self).__init__(parent)
self.tabWidget = QTabWidget()
self.tabWidget.tab1 = QWidget()
self.tabWidget.tab2 = QWidget()
self.tabWidget.tab3 = QWidget()
self.tabWidget.addTab(self.tabWidget.tab1,"Tab 1")
self.tabWidget.addTab(self.tabWidget.tab2,"Tab 2")
self.tabWidget.addTab(self.tabWidget.tab3,"Tab 3")
self.tab1UI()
self.tab2UI()
self.tab3UI()
self.setWindowTitle("tab demo")
# Here is the addition to the code.
mainLayout = QVBoxLayout()
mainLayout.addWidget(self.tabWidget)
self.setLayout(mainLayout)

Related

Widgets cross over the tab on Pyqt5

I am trying to build a simple desktop application which can show and play all the movies in one place. This app includes several tabs, which contain different categories of movies.
The problem is the widgets i put inside the tab windows cross over the tab title. I don't know why.
This is my code:
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
class Filmler(QTabWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("Filmler")
self.setWindowIcon(QIcon("film.jpg"))
self.setGeometry(200,100,1000,500)
self.tab1 = QWidget()
self.tab2 = QWidget()
self.tab3 = QWidget()
self.tab4 = QWidget()
self.tab1UI()
self.tab2UI()
self.tab3UI()
self.tab4UI()
self.addTab(self.tab1, "Hollywood")
self.addTab(self.tab2, "Bollywood")
self.addTab(self.tab3, "Uyghur")
self.addTab(self.tab4, "Zumra'nin Filmleri")
self.show()
def tab1UI(self):
# adding variables
# 1st movie
movie1_poster = QLabel()
movie1_poster.setPixmap(QPixmap("equalizer2.jpg"))
movie1_name = QLabel("Equalizer 2")
movie1_name.setAlignment(Qt.AlignCenter)
movie1_name.setFont(QFont("Times", 13))
movie1_link = QPushButton("izle")
vbox1 = QVBoxLayout()
vbox1.addWidget(movie1_name)
vbox1.addWidget(movie1_poster)
vbox1.addWidget(movie1_link)
vbox1.addStretch()
hbox = QHBoxLayout()
hbox.addLayout(vbox1)
hbox.addStretch()
self.setLayout(hbox)
def tab2UI(self):
pass
def tab3UI(self):
pass
def tab4UI(self):
pass
app = QApplication(sys.argv)
filmler = Filmler()
sys.exit(app.exec_())
This is the result.
Set parent self.tab1 to QHBoxLayout
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
class Filmler(QTabWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("Filmler")
self.setWindowIcon(QIcon("film.jpg"))
self.setGeometry(200,100,1000,500)
self.tab1 = QWidget()
self.tab2 = QWidget()
self.tab3 = QWidget()
self.tab4 = QWidget()
self.tab1UI()
self.tab2UI()
self.tab3UI()
self.tab4UI()
self.addTab(self.tab1, "Hollywood")
self.addTab(self.tab2, "Bollywood")
self.addTab(self.tab3, "Uyghur")
self.addTab(self.tab4, "Zumra'nin Filmleri")
self.show()
def tab1UI(self):
# adding variables
# 1st movie
movie1_poster = QLabel()
movie1_poster.setPixmap(QPixmap("lena.jpg"))
movie1_name = QLabel("Equalizer 2")
movie1_name.setAlignment(Qt.AlignCenter)
movie1_name.setFont(QFont("Times", 13))
movie1_link = QPushButton("izle")
vbox1 = QVBoxLayout()
vbox1.addWidget(movie1_name)
vbox1.addWidget(movie1_poster)
vbox1.addWidget(movie1_link)
vbox1.addStretch()
hbox = QHBoxLayout(self.tab1) # + self.tab1
hbox.addLayout(vbox1)
hbox.addStretch()
# self.setLayout(hbox) # ---
def tab2UI(self):
pass
def tab3UI(self):
pass
def tab4UI(self):
pass
app = QApplication(sys.argv)
filmler = Filmler()
sys.exit(app.exec_())

PyQt not displaying pixmap properly

So I'm new to PyQt and I can't seem to quite work out all the kinks. For some reason, whenever I click the "play game" button, the image just doesn't appear. However, it does run the InitUI. Can someone tell me what Im doing wrong? (when It just loaded up the image initially, the image appeared.
class Example(QMainWindow):
def __init__(self):
super().__init__()
self.title = 'PyQt5 image - pythonspot.com'
self.initUI()
def initUI(self):
central_widget = QWidget()
self.chess = ChessWidget(central_widget)
self.setCentralWidget(central_widget)
self.setWindowIcon(QIcon('web.png'))
self.resize(900,900)
self.center()
self.setFixedSize(self.size())
self.show()
def toggleMenu(self, state):
if state:
self.statusbar.show()
else:
self.statusbar.hide()
# def closeEvent(self, event):
#
# reply = QMessageBox.question(self, 'Message',
# """Are you sure you want to quit?""", QMessageBox.Yes |
# QMessageBox.No, QMessageBox.No)
#
# if reply == QMessageBox.Yes:
# event.accept()
# else:
# event.ignore()
def center(self):
qr = self.frameGeometry()
cp = QDesktopWidget().availableGeometry().center()
qr.moveCenter(cp)
self.move(qr.topLeft())
class ChessWidget(QFrame):
def __init__(self, parent):
super().__init__(parent)
qbtn = QPushButton('Play Game', self)
qbtn.clicked.connect(lambda: qbtn.close())
qbtn.clicked.connect(lambda: self.initUI())
qbtn.resize(qbtn.sizeHint())
hbox = QHBoxLayout()
hbox.addStretch(1)
hbox.addWidget(qbtn)
vbox = QVBoxLayout()
vbox.addStretch(1)
vbox.addLayout(hbox)
self.setLayout(vbox)
def initUI(self):
print("hi")
pixmap = QPixmap("ChessBoard.jpg")
lbl = QLabel(self)
pixmap2 = pixmap.scaledToWidth(900)
hbox = QHBoxLayout(self)
hbox.addStretch(1)
hbox.addWidget(lbl)
lbl.setPixmap(pixmap2) ` if __name__ == '__main__':
app = QApplication([])
ex = Example()
sys.exit(app.exec_()) `
You should be getting a useful warning from Qt; if not, check that your test environment has a console active. The warning is:
QLayout: Attempting to add QLayout "" to ChessWidget "", which already has a layout
This happens when you create the QHBoxLayout in ChessWidget.initUI and try to parent it to the ChessWidget. You have already set a QVBoxLayout on that widget.
A quick solution is to retain the name of your layout (vbox -> self.vbox), then in a click event remove the QPushButton from the layout and add the ChessWidget.
I understand you're just making small tests for learning purposes, but this design pattern with the QPushButton being permanently replaced might not be what you want. If you want the QPushButton and ChessWidget to occupy the same space, look at QStackedWidget. This will allow you to switch from one widget to the other as often as you like. This could be a useful approach if you want to hide the ChessWidget later when no game is active, for example.
Note that when you create your QPushButton and QLabel, it's unnecessary to parent them to the ChessWidget as they will be reparented to the layout when added.
Try it:
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
class Example(QMainWindow):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
central_widget = QWidget()
self.chess = ChessWidget(central_widget)
self.setCentralWidget(central_widget)
self.layV = QVBoxLayout(central_widget) # +++
self.layV.addWidget(self.chess) # +++
self.setWindowIcon(QIcon('D:/_Qt/img/py-qt.png')) # web.png
self.resize(440,440) #(900,900)
class ChessWidget(QFrame):
def __init__(self, parent=None):
super().__init__(parent)
qbtn = QPushButton('Play Game', self)
qbtn.clicked.connect(lambda: qbtn.close())
qbtn.clicked.connect(lambda: self.initUI())
self.hbox = QHBoxLayout()
self.hbox.addWidget(qbtn)
self.vbox = QVBoxLayout()
self.vbox.addStretch(1)
self.vbox.addLayout(self.hbox)
self.setLayout(self.vbox)
def initUI(self):
print("hi")
pixmap = QPixmap("D:/_Qt/img/pyqt.jpg") # ChessBoard.jpg
lbl = QLabel(self)
self.vbox.addWidget(lbl)
lbl.setPixmap(pixmap.scaled(400, 400, Qt.KeepAspectRatio)) # +++
if __name__ == '__main__':
app = QApplication([])
ex = Example()
ex.setWindowTitle('PyQt5 image - pythonspot.com')
ex.show()
sys.exit(app.exec_())

Adding QScrollArea to QTabWidget

I'm trying to add a scroll area to a QTabWideget.
At the moment I've set it up with two different tabs and the scrollArea is added to the second tab.
When I run my program, items are added to the scrollArea and the scroll bar is visible(policy set to always show), but it's greyed out.
Code:
class MyTableWidget(QWidget):
def __init__(self, parent):
super(QWidget, self).__init__(parent)
self.layout = QVBoxLayout(self)
# Initialize tab screen
self.tabs = QTabWidget()
self.tab1 = QWidget()
self.tab2 = QScrollArea()
self.tabs.setMaximumWidth(300)
self.tabs.setMaximumHeight(100)
# Add tabs
self.tabs.addTab(self.tab1,"Tab 1")
self.tabs.addTab(self.tab2,"Tab 2")
# Create first tab
# ...
# Create second tab
self.tab2.layout = QFormLayout(self)
self.tab2.setWidgetResizable(True)
self.tab2.setVerticalScrollBar(QScrollBar())
self.tab2.setVerticalScrollBarPolicy(2)
self.tab2.setFixedSize(100, 70)
self.t1 = QLabel('Test1', self)
self.t2 = QLabel('Test2', self)
self.t3 = QLabel('Test3', self)
self.t4 = QLabel('Test4', self)
self.t5 = QLabel('Test5', self)
self.t6 = QLabel('Test6', self)
self.tab2.layout.addRow(self.t1)
self.tab2.layout.addRow(self.t2)
self.tab2.layout.addRow(self.t3)
self.tab2.layout.addRow(self.t4)
self.tab2.layout.addRow(self.t5)
self.tab2.layout.addRow(self.t6)
self.tab2.setLayout(self.tab2.layout)
# Add tabs to widget
self.layout.addWidget(self.tabs)
self.setLayout(self.layout)
Code above turns out like this:
All squished together. I would like to be able to scroll and add more data without squishing whats there already.
Also, can I make the scroll area have the same background as seen in the picture below?
You do not have to replace the QScrollArea layout but add a new widget that has the QFormLayout as shown below.
from PyQt5.QtWidgets import QWidget, QVBoxLayout, QApplication, \
QTabWidget, QScrollArea, QFormLayout, QLabel
class MyTableWidget(QWidget):
def __init__(self, parent=None):
super(QWidget, self).__init__(parent)
self.layout = QVBoxLayout(self)
self.tabs = QTabWidget()
self.tab1 = QWidget()
self.tab2 = QScrollArea()
self.tabs.addTab(self.tab1, 'Tab 1')
self.tabs.addTab(self.tab2, 'Tab 2')
content_widget = QWidget()
self.tab2.setWidget(content_widget)
flay = QFormLayout(content_widget)
self.tab2.setWidgetResizable(True)
self.t1 = QLabel('Test1')
self.t2 = QLabel('Test2')
self.t3 = QLabel('Test3')
self.t4 = QLabel('Test4')
self.t5 = QLabel('Test5')
self.t6 = QLabel('Test6')
flay.addRow(self.t1)
flay.addRow(self.t2)
flay.addRow(self.t3)
flay.addRow(self.t4)
flay.addRow(self.t5)
flay.addRow(self.t6)
self.layout.addWidget(self.tabs)
self.resize(300, 100)
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
w = MyTableWidget()
w.show()
sys.exit(app.exec_())

Can't open gui class window with specified options

I'm new to python and pyqt. I'm trying to open a new window after the first screen. My second window opens but without the options I specified, label and pushbutton.
from PyQt5 import QtWidgets
import sys
class secondwindow(QtWidgets.QMainWindow):
def __init__(self):
super(secondwindow, self).__init__()
self.label1 = QtWidgets.QLabel("Second Window");
self.button1 = QtWidgets.QPushButton("Click Me");
hbox = QtWidgets.QHBoxLayout()
hbox.addWidget(self.label1)
hbox.addWidget(self.button1)
self.setLayout(hbox)
class Window(QtWidgets.QWidget):
def btnclicked(self):
sender = self.sender()
if sender.text() == "OK":
self.secwin.show()
def __init__(self, parent=None):
super(Window, self).__init__(parent)
self.button1 = QtWidgets.QPushButton("OK");
vbox = QtWidgets.QVBoxLayout()
vbox.addWidget(self.button1)
self.setLayout(vbox)
self.button1.clicked.connect(self.btnclicked)
self.secwin = secondwindow()
self.show()
def main():
app = QtWidgets.QApplication(sys.argv)
main = Window()
main.show
sys.exit(app.exec())
if __name__ == '__main__':
main()
QMainWindow is a special widget because it has a defined structure, http://doc.qt.io/qt-5/qmainwindow.html#qt-main-window-framework:
As shown in the image there is already an area destined to place the widgets called Central Widget, in it you must place the widgets that you want to be displayed for it, you use setCentralWidget().
In your case the solution is:
class secondwindow(QtWidgets.QMainWindow):
def __init__(self):
super(secondwindow, self).__init__()
central_widget = QtWidgets.QWidget()
self.label1 = QtWidgets.QLabel("Second Window")
self.button1 = QtWidgets.QPushButton("Click Me")
hbox = QtWidgets.QHBoxLayout(central_widget)
hbox.addWidget(self.label1)
hbox.addWidget(self.button1)
self.setCentralWidget(central_widget)

PYQT - Qframe - Show/Hide without shifting the rest of the window

I got the following Test-GUI.
There is a left layout and a right layout where i want to put buttons and other things onto. The button on the right should make a QFrame unhide or hide and all the widgets in it. This works.
But after the first two clicks, the layout is different.
The TableWidget on the left layout gets resized and the button is a bit more south.
Is there an easy way to fix this?
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.main_widget = MainWidget()
self.setCentralWidget(self.main_widget)
self.show()
class MainWidget(QWidget):
def __init__(self):
super().__init__()
self.layout = QVBoxLayout()
self.tab_widget = TabWidget()
self.debugger = Dialog()
self.layout.addWidget(self.tab_widget)
self.layout.addWidget(self.debugger)
self.setLayout(self.layout)
class TabWidget(QTabWidget):
def __init__(self):
super().__init__()
self.tab1 = Tab_1()
self.addTab(self.tab1, "Tab1")
class Tab_1(QWidget):
def __init__(self):
super().__init__()
# LEFT LAYOUT BEGIN
self.table = QTableWidget()
self.table.setRowCount(1)
self.table.setColumnCount(2)
self.table.setSizeAdjustPolicy(QAbstractScrollArea.AdjustToContents)
self.table.resizeColumnsToContents()
left_hlayout = QHBoxLayout()
left_hlayout.addWidget(self.table)
# # LEFT LAYOUT END
#
# # RIGHT LAYOUT BEGIN
self.button_options = QPushButton('Options')
self.button_options.setCheckable(True)
self.button_options.toggled.connect(self.option_pressed)
right_vlayout = QVBoxLayout()
right_vlayout.addWidget(self.button_options)
# # RIGHT LAYOUT END
# MAIN LAYOUT BEGING
self.main_layout = QVBoxLayout()
self.horizontal_layout = QHBoxLayout()
self.horizontal_layout.addLayout(left_hlayout)
self.horizontal_layout.addLayout(right_vlayout)
self.main_layout.addLayout(self.horizontal_layout)
self.option = Options()
self.main_layout.addWidget(self.option)
self.setLayout(self.main_layout)
# MAIN LAYOUT END
def option_pressed(self):
if self.button_options.isChecked():
self.option.setVisible(True)
else:
self.option.setVisible(False)
class Options(QFrame):
def __init__(self):
super().__init__()
self.hide()
self.setFrameStyle(QFrame.StyledPanel | QFrame.Sunken)
self.options_layout = QFormLayout()
self.options_label = QLabel('One')
self.options_lineedit = QLineEdit('Two')
self.options_layout.addRow(self.options_label, self.options_lineedit)
self.setLayout(self.options_layout)
class Dialog(QPlainTextEdit):
def __init__(self, parent=None):
super().__init__(parent)
self.setFixedHeight(100)
pal = QPalette()
bgc = QColor(210, 210, 210)
pal.setColor(QPalette.Base, bgc)
self.setPalette(pal)
if __name__ == "__main__":
app = QApplication(sys.argv)
window = MainWindow()
sys.exit(app.exec_())

Categories

Resources