button overlapping checkbox text - python

I try to code in PyQt an interface where user can check boxes and then click on the button to process their choices. However, I have some trouble because the button overlaps checkbox labels. Here is a simpler code to show you my problem :
from PyQt5.QtWidgets import QMainWindow, QApplication, QPushButton, QWidget, QTabWidget, QVBoxLayout, QGridLayout, \
QCheckBox, QHBoxLayout
import sys
class App(QMainWindow):
def __init__(self):
super().__init__()
self.title = 'PyQt5 tabs - pythonspot.com'
self.left = 0
self.top = 0
self.width = 300
self.height = 200
self.setWindowTitle(self.title)
self.setGeometry(self.left, self.top, self.width, self.height)
self.table_widget = MyTableWidget(self)
self.setCentralWidget(self.table_widget)
self.show()
class MyTableWidget(QWidget):
def __init__(self, parent):
super(QWidget, self).__init__(parent)
self.layout = QVBoxLayout(self)
# Initialize tab screen
self.tabs = QTabWidget()
self.tab2 = QWidget()
self.tabs.resize(300, 200)
self.checkbox_states = {}
# Add tabs
self.tabs.addTab(self.tab2, "Tab 2")
# Create first tab
self.tab2.layout = QGridLayout()
checkbox_layout = QVBoxLayout()
self.checkbox_states["Haar"] = QCheckBox("small")
self.checkbox_states["db"] = QCheckBox("small")
self.checkbox_states["sym"] = QCheckBox("small")
self.checkbox_states["coif"] = QCheckBox("very very very very long")
for key, l in self.checkbox_states.items():
l.setChecked(False)
checkbox_layout.addWidget(l)
process_button_layout = QHBoxLayout()
self.process_wavelet = QPushButton("Process")
process_button_layout.addWidget(self.process_wavelet)
# QObject.connect(self.process_wavelet, SIGNAL('clicked()'), self._on_process_wavelet)
self.tab2.layout.addLayout(checkbox_layout, 0, 0, 0, 0)
self.tab2.layout.addLayout(process_button_layout, 1, 1, 1, 1)
self.tab2.setLayout(self.tab2.layout)
# Add tabs to widget
self.layout.addWidget(self.tabs)
self.setLayout(self.layout)
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = App()
sys.exit(app.exec_())
Does anyone has an idea on how i can suppress this overlapping problem ? Thanks !
EDIT :
I would like something like this :
Here with a much smaller text, I don't have the overlapping problem. It only appear if we replace the last checkbox's label by a longer string.

What the OP wants can be obtained from many depending on how he wants the geometries of the elements to behave when the window changes in size. So as there are no more restrictions than the image it shows, it will provide a possible solution using QGridLayout where in the first column the QCheckBox will be placed, and in the second column and in the last file the QPushButton:
class MyTableWidget(QWidget):
def __init__(self, parent):
super(QWidget, self).__init__(parent)
layout = QVBoxLayout(self)
self.tabs = QTabWidget()
self.tabs.resize(300, 200)
layout.addWidget(self.tabs)
self.tab2 = QWidget()
self.tabs.addTab(self.tab2, "Tab 2")
lay = QGridLayout(self.tab2)
self.checkbox_states = {}
for i, (key, text) in enumerate(
(
("Haar", "small"),
("db", "small"),
("sym", "small"),
("coif", "very very very very long"),
)
):
checkbox = QCheckBox(text)
checkbox.setChecked(False)
lay.addWidget(checkbox, i, 0)
self.checkbox_states[key] = checkbox
self.process_wavelet = QPushButton("Process")
lay.addWidget(self.process_wavelet, i, 1)

Related

Display a QLabel at the top-centre of the window

I'm having trouble setting up PyQt on my own. My idea its to creat a music-player with a song title and album cover. I have had success in creating my own window and adding the album cover. But I can't add the label in the right position. I want the song title to be at the top-center of the window, like the image below:
I have tried a lot of ways, but had no luck.
import sys
from PyQt5.QtGui import QIcon, QPixmap, QFontDatabase, QFont
from PyQt5.QtWidgets import QApplication, QLabel, QMainWindow, QWidget, QGridLayout, QDialog
from PyQt5.QtCore import Qt, QRect
# Subclass QMainWindow to customise your application's main window
class MainWindow(QMainWindow):
def __init__(self, *args, **kwargs):
super(MainWindow, self).__init__(*args, **kwargs)
self.title = 'PyQt5 simple window - pythonspot.com'
self.left = 10
self.top = 10
self.width = 480
self.height = 320
self.initUI()
self.setWindowTitle("My Awesome App")
def add_font(self):
# Load the font:
font_db = QFontDatabase()
font_id = font_db.addApplicationFont('American Captain.ttf')
families = font_db.applicationFontFamilies(font_id)
ttf_font = QFont(' '.join(families), 15)
return ttf_font
def initUI(self):
ttf_font = self.add_font()
w = QWidget()
self.setWindowTitle(self.title)
self.setGeometry(self.left, self.top, self.width, self.height)
self.show()
album_cover = QLabel(self)
album_pic = QPixmap('resized_image.jpg')
album_cover.setPixmap(album_pic)
album_cover.setAlignment(Qt.AlignCenter)
self.setCentralWidget(album_cover)
art_alb = QLabel(self)
art_alb.setFont(ttf_font)
art_alb.setText("michael buble - christmas")
art_alb.setGeometry(self.x, self.y, self.x, self.y)
art_alb.setAlignment(Qt.AlignTop | Qt.AlignCenter )
art_alb.show()
self.show()
app = QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec_()
You should use a central widget with a layout to control how the child widgets are sized and positioned in the main window. Here is a re-write of your initUI method that should do what you want:
class MainWindow(QMainWindow):
...
def initUI(self):
self.setWindowTitle(self.title)
self.setGeometry(self.left, self.top, self.width, self.height)
widget = QWidget()
layout = QGridLayout(widget)
art_alb = QLabel(self)
ttf_font = self.add_font()
art_alb.setFont(ttf_font)
art_alb.setText("michael buble - christmas")
layout.addWidget(art_alb, 0, 0, Qt.AlignTop | Qt.AlignHCenter)
album_cover = QLabel(self)
album_pic = QPixmap('image.jpg')
album_cover.setPixmap(album_pic)
layout.addWidget(album_cover, 1, 0, Qt.AlignHCenter)
layout.setRowStretch(1, 1)
self.setCentralWidget(widget)
Note that there's no need to keep calling show(), since this is all handled automatically by the layout. For more information, see the Layout Management article in the Qt docs.

Getting value from push button that I can use in a new class/window

I want the first window that opens up to contain 4 push buttons responding to the numbers: 2,3,4,5. Once I have pressed one of these buttons I want the window to close and a new window to open with a label (just so I know it works) and also to use that number as a separate variable as it will select a sheet that I am reading from an excel file.
At the moment I can create the first window with the boxes, and when I press one the new window opens - but I cannot get the selection I made to come across.
Here is as far as I have got so far...
import sys
from PyQt5.QtWidgets import QApplication, QLabel, QPushButton, QHBoxLayout, QGroupBox, QDialog, QVBoxLayout, QMainWindow
# select floor window
class select_floor_window(QDialog):
def __init__(self, parent=None):
super().__init__()
self.title = 'Select floor'
self.left = 10
self.top = 10
self.width = 320
self.height = 100
self.selection_ui()
def selection_ui(self):
self.setWindowTitle(self.title)
self.setGeometry(self.left, self.top, self.width, self.height)
self.createHorizontalLayout()
windowLayout = QVBoxLayout()
windowLayout.addWidget(self.horizontalGroupBox)
self.setLayout(windowLayout)
self.show()
def createHorizontalLayout(self):
# box layout
self.horizontalGroupBox = QGroupBox("Which floor are you on?")
layout = QHBoxLayout()
# floor buttons
floor_2_button = QPushButton("2", self)
floor_2_button.clicked.connect(self.on_click2)
layout.addWidget(floor_2_button)
floor_3_button = QPushButton("3", self)
floor_3_button.clicked.connect(self.on_click3)
layout.addWidget(floor_3_button)
floor_4_button = QPushButton("4", self)
floor_4_button.clicked.connect(self.on_click4)
layout.addWidget(floor_4_button)
floor_5_button = QPushButton("5", self)
floor_5_button.clicked.connect(self.on_click5)
layout.addWidget(floor_5_button)
self.horizontalGroupBox.setLayout(layout)
# close this window and load main window
def on_click2(self):
self.floorchoice = 2
self.show_main = main_Window()
self.show_main.show()
self.hide()
print("2")
return floorchoice
def on_click3(self):
self.floorchoice = 3
self.show_main = main_Window()
self.show_main.show()
self.hide()
print("3")
return floorchoice
def on_click4(self):
self.floorchoice = 4
self.show_main = main_Window()
self.show_main.show()
self.hide()
print("4")
return floorchoice
def on_click5(self):
self.floorchoice = 5
self.show_main = main_Window()
self.show_main.show()
self.hide()
print("5")
return floorchoice
# create main window
class main_Window(QMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self.title = "2ndwindow"
self.top = 100
self.left = 100
self.width = 680
self.height = 500
show_floor_button = QLabel(floorchoice, self)
show_floor_button.move(100,100)
# Close app button
close_app_button = QPushButton("Exit", self)
close_app_button.move(400,400)
close_app_button.setToolTip("Close application")
close_app_button.clicked.connect(self.CloseApp)
self.InitWindow()
# showing window
def InitWindow(self):
self.setWindowTitle(self.title)
self.setGeometry(self.top, self.left, self.width, self.height)
self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = select_floor_window()
sys.exit(app.exec_())
Anyway that I try to set up the code, it always says that "name 'floorchoice' is not defined" in the second window, and cannot get it to display the result from the first class.
The functions that are invoked do not return anything, plus self.floorchoice is different floorchoice, the first is an attribute of the class and the other is a local variable.
What you have to do is that the class through the constructor or another method get that information.
In the next one I add one more argument to the invocation using functool.partial, then I pass that argument to the constructor of the other window so that I get that information.
I think your main error is caused by not taking into account that each variable, instance, object, etc. has a scope within the application.
import sys
from PyQt5.QtWidgets import QApplication, QLabel, QPushButton, QHBoxLayout, QGroupBox, QDialog, QVBoxLayout, QMainWindow
from functools import partial
# select floor window
class select_floor_window(QDialog):
def __init__(self, parent=None):
super().__init__()
self.title = "Select floor"
self.left = 10
self.top = 10
self.width = 320
self.height = 100
self.selection_ui()
def selection_ui(self):
self.setWindowTitle(self.title)
self.setGeometry(self.left, self.top, self.width, self.height)
self.createHorizontalLayout()
windowLayout = QVBoxLayout(self)
windowLayout.addWidget(self.horizontalGroupBox)
def createHorizontalLayout(self):
# box layout
self.horizontalGroupBox = QGroupBox("Which floor are you on?")
layout = QHBoxLayout()
self.horizontalGroupBox.setLayout(layout)
# floor buttons
for option in (2, 3, 4, 5):
button = QPushButton(str(option))
layout.addWidget(button)
wrapper = partial(self.on_click, option)
button.clicked.connect(wrapper)
# close this window and load main window
def on_click(self, option):
self.show_main = main_Window(option)
self.show_main.show()
self.hide()
# create main window
class main_Window(QMainWindow):
def __init__(self, option, parent=None):
super().__init__(parent)
self.title = "2ndwindow"
self.top = 100
self.left = 100
self.width = 680
self.height = 500
show_floor_button = QLabel(str(option), self)
show_floor_button.move(100, 100)
# Close app button
close_app_button = QPushButton("Exit", self)
close_app_button.move(400, 400)
close_app_button.setToolTip("Close application")
close_app_button.clicked.connect(self.close)
self.InitWindow()
# showing window
def InitWindow(self):
self.setWindowTitle(self.title)
self.setGeometry(self.top, self.left, self.width, self.height)
if __name__ == "__main__":
app = QApplication(sys.argv)
ex = select_floor_window()
ex.show()
sys.exit(app.exec_())

PyQt5 QMainWindow, QDockWidget, fitting autosize with screensize

I've created aQMainWindow with menubar and 4 dockable widgets. First dockwidget contents multipletabs, second is Qpainter widget, third is Matlabplot and fourth is pdf report.
When I run the code shows up like this below.
I want to be like below.
I want to divide screen into four widget automatically whenever it runs at any screen, And I want to have tabs to resize to its content.
Or do you have any better idea of having such widget, you are welcome to come with it.
Update of code
Resize of Qdockwidget brings this post forward. It seems that Qt Qdockwidget resize has been an issue for long time ago. I find it very difficult to program my Qmainwindow with 4 Qdockwidget, which the dock would fit and resize according to its contents, with other words, child widget. and According to Qt documentation, Qdockwidget resizes and respect the size of child Widgets. to get straight to problem, my mainwindow has 4 qdockwidgets, I would like to have them resizable according to contents.
What I have tried and used so far.
I have used following size functions.
self.sizeHint, self.minimumSize(), self.maximumSize() and self.setFixedSize(self.sizeHint()).
I am able to fix the size of contents in first Qdockwidget by using following codes.
self.setFixedSize(self.sizeHint())
Above code is written in the child widgets Class widgets
But that is not enough in order to work it, despite following codes needed to run and effect.
self.first.setMinimumSize(self.first.sizeHint())
self.grid.setMinimumSize(self.grid.sizeHint())
self.third.setMinimumSize(self.third.sizeHint())
self.adjustSize()
self.first.setMinimumSize(self.first.minimumSizeHint())
self.grid.setMinimumSize(self.grid.minimumSizeHint())
self.third.setMinimumSize(self.third.minimumSizeHint())
Noting that still my dockwindow does not resize according to child widgets. Dockwidget expand and increase. One may ask, Qdockwidgets could arrange and control by resizeDocks(). This code line is used and tried, but still does not get the desired behaviour.
I have been looking around and could find some relevant questions.
C++ resize a docked Qt QDockWidget programmatically?
Forcing a QDockWidget to behave like a central widget when it comes to resizing
Create a QDockWidget that resizes to it's contents
Those questions do not solve my problem.
Visualization of my code launch
1- When code runs and display on screen.
2- Desired and wanted display by first run of software.
3- When user tabs between tabwidgets want to resize to its content as image below.
4- The code is given below.
import sys, os
from PyQt5 import QtCore, QtWidgets, QtGui
from PyQt5.QtWidgets import QMainWindow, QLabel, QGridLayout, QWidget,
QDesktopWidget, QApplication, QAction, QFileDialog,QColorDialog
from PyQt5.QtWidgets import QPushButton, QMessageBox, QDockWidget,
QTabWidget, QVBoxLayout, QGroupBox, QHBoxLayout, QFrame, QSplitter
from PyQt5.QtWidgets import QTableWidget, QRadioButton, QListWidget,
QCheckBox, QTextEdit, QDialog, QSizePolicy
from PyQt5.QtCore import QSize, Qt, QFileInfo, QFile
from PyQt5.QtGui import QIcon, QKeySequence, QPainter, QPalette, QPen,
QBrush, QTextCursor, QFont
import matplotlib.pyplot as plt
#plt.style.use('ggplot')
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar
import seaborn as sns
iconroot = os.path.dirname(__file__)
class mywindow(QMainWindow):
def __init__(self):
super(mywindow, self).__init__()
self.setMinimumSize(QSize(1200,800))
self.setWindowTitle('My Graphic Window')
centralWidget = QWidget(self)
self.setCentralWidget(centralWidget)
gridLayout = QGridLayout(self)
centralWidget.setLayout(gridLayout)
qtRectangle = self.frameGeometry()
centerPoint = QDesktopWidget().availableGeometry().center()
qtRectangle.moveCenter(centerPoint)
self.move(qtRectangle.topLeft())
imageroot = QFileInfo(__file__).absolutePath()
# Greate new action
newaction = QAction(QIcon(imageroot +'/images/new.png'), '&New', self)
newaction.setShortcut('Ctrl+N')
newaction.setStatusTip('New document')
newaction.triggered.connect(self.newCall)
# Greate menu bar and add action
menubar = self.menuBar()
filemenu = menubar.addMenu('&Test')
filemenu.addAction(newaction)
# Get current screen geometry
self.Screen = QtWidgets.QDesktopWidget().screenGeometry()
print(self.Screen, self.Screen.height(), self.Screen.width())
# def createToolbar(self):
self.filetoolbar = self.addToolBar('File')
self.filetoolbar.addAction(newaction)
self.topleftdockwindow()
self.toprightdockwindow()
def newCall(self):
print('New')
# Greate dockable subwindow.
def topleftdockwindow(self):
topleftwindow = QDockWidget ('Info',self)
# Stick window to left or right
topleftwindow.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea)
self.addDockWidget(Qt.TopDockWidgetArea, topleftwindow)
topleftwindow.setWidget(createtabwidget())
topleftwindow.resize( topleftwindow.minimumSize() )
bottomleftwindow = QDockWidget("Matplot",self)
bottomleftwindow.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea)
self.addDockWidget(Qt.BottomDockWidgetArea, bottomleftwindow)
bottomleftwindow.setWidget(createplotwidget())
self.setDockNestingEnabled(True)
topleftwindow.resize( topleftwindow.minimumSize() )
self.splitDockWidget(topleftwindow, bottomleftwindow , Qt.Vertical)
#self.resizeDocks((topleftwindow, bottomleftwindow), (40,20),
#Qt.Horizontal)
# Greate topright dockwindow.
def toprightdockwindow(self):
toprightdock = QDockWidget ('Plot',self)
toprightdock = QDockWidget ('Plot',self)
toprightdock.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea)
self.addDockWidget(Qt.TopDockWidgetArea, toprightdock)
#self.setDockOptions(self.AnimatedDocks | self.AllowNestedDocks)
toprightdock.setWidget(createpaintwidget())
toprightdock.setFloating( True )
bottomrightdock = QDockWidget("Technical report",self)
bottomrightdock.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea)
self.addDockWidget(Qt.BottomDockWidgetArea, bottomrightdock)
bottomrightdock.setWidget(QtWidgets.QListWidget())
self.splitDockWidget(toprightdock, bottomrightdock, Qt.Vertical)
class createpaintwidget(QWidget):
def __init__(self):
super().__init__()
self.setBackgroundRole(QPalette.Base)
self.setAutoFillBackground(True)
self.sizeHint()
self.adjustSize()
def paintEvent(self, event):
self.pen = QPen()
self.brush = QBrush(Qt.gray,Qt.Dense7Pattern)
painter = QPainter(self)
painter.setPen(self.pen)
painter.setBrush(self.brush)
painter.drawRect(100,100,250,250)
painter.setBrush(QBrush())
painter.drawEllipse(400,100,200,200)
class createplotwidget(QWidget):
def __init__(self):
super().__init__()
self.initializewidget()
self.plot1()
self.setMaximumSize(self.sizeHint())
self.adjustSize()
def initializewidget(self):
self.setWindowTitle("Plotting M&N")
gridlayout = QGridLayout()
self.setLayout(gridlayout)
self.figure = plt.figure(figsize=(15,5))
self.canvas = FigureCanvas(self.figure)
self.toolbar = NavigationToolbar(self.canvas,self)
gridlayout.addWidget(self.canvas,1,0,1,2)
gridlayout.addWidget(self.toolbar,0,0,1,2)
def plot1(self):
# sns.set()
ax = self.figure.add_subplot(111)
x = [i for i in range(100)]
y = [i**2 for i in x]
ax.plot(x,y, 'b.-')
ax.set_title('Quadratic Plot')
self.canvas.draw()
class createtextdocument(QWidget):
def __init__(self):
super().__init__()
self.textedit()
def textedit(self):
self.textedit = QTextEdit()
self.cursor = self.textedit.textCursor()
class createtabwidget(QDialog):
def __init__(self):
super().__init__()
# Greate tabs in dockable window
tab = QTabWidget()
scroll = QScrollArea()
ncroll = QScrollArea()
mcroll = QScrollArea()
self.first = firsttabgeometry()
self.grid = Grid()
self.third = thirdtabloads()
scroll.setWidget(self.first)
ncroll.setWidget(self.grid)
mcroll.setWidget(self.third)
scroll.setWidgetResizable(True)
self.first.setMinimumSize(self.first.sizeHint())
self.grid.setMinimumSize(self.grid.sizeHint())
self.third.setMinimumSize(self.third.sizeHint())
self.adjustSize()
self.first.setMinimumSize(self.first.minimumSizeHint())
self.grid.setMinimumSize(self.grid.minimumSizeHint())
self.third.setMinimumSize(self.third.minimumSizeHint())
# Adding multiple tabslides
tab.addTab(self.first,'One')
tab.addTab(self.grid,'Two')
tab.addTab(self.third,'Three')
tab.setFont(QFont("Georgia",10,QFont.Normal))
vboxlayout = QVBoxLayout()
vboxlayout.addWidget(tab)
self.setLayout(vboxlayout)
class firsttabgeometry(QWidget):
def __init__(self):
super().__init__()
self.setFixedSize(self.sizeHint())
iconroot = QFileInfo(__file__).absolutePath()
font = QFont("Georgia",10,QFont.Normal)
# Add widget and buttons to tabs
sectiontypegroupbox = QGroupBox('&One',self)
sectiontypegroupbox.setFont(QFont("Georgia",10,QFont.Normal))
tab1button = QPushButton('')
tab1button.setIcon(QIcon(iconroot +'/images/circularcolumn'))
tab1button.setIconSize(QSize(60,60))
tab1button.clicked.connect(self.One)
squarebutton = QPushButton('')
squarebutton.setIcon(QIcon(iconroot +'/images/squarecolumn'))
squarebutton.setIconSize(QSize(60,60))
squarebutton.clicked.connect(self.Two)
wallbutton = QPushButton("")
wallbutton.setIcon(QIcon(iconroot +'/images/wall'))
wallbutton.setIconSize(QSize(60,60))
wallbutton.clicked.connect(self.Three)
circularlabel = QLabel(" One",self)
circularlabel.setSizePolicy(QSizePolicy.Expanding,QSizePolicy.Expanding)
circularlabel.setFont(font)
sclabel = QLabel(" Two",self)
sclabel.setSizePolicy(QSizePolicy.Expanding,QSizePolicy.Expanding)
sclabel.setFont(font)
walllabel = QLabel(" Three",self)
walllabel.setSizePolicy(QSizePolicy.Expanding,QSizePolicy.Expanding)
walllabel.setFont(font)
bottomgroupbox = QGroupBox("Group 2")
vboxlayout = QHBoxLayout()
vboxlayout.addStretch()
radiobutton2 = QRadioButton("Radio Button")
radiobutton3 = QRadioButton("Radio Button")
testbutton2 = QPushButton('Test Button 2')
vboxlayout.addWidget(radiobutton2)
vboxlayout.addWidget(radiobutton3)
vboxlayout.addWidget(testbutton2)
bottomgroupbox.setLayout(vboxlayout)
mainlayout = QGridLayout()
mainlayout.addWidget(tab1button,0,0)
mainlayout.addWidget(circularlabel,0,1)
mainlayout.addWidget(squarebutton,1,0)
mainlayout.addWidget(sclabel,1,1)
mainlayout.addWidget(wallbutton,2,0)
mainlayout.addWidget(walllabel,2,1)
mainlayout.setContentsMargins(200,50,50,50)
sectiontypegroupbox.setLayout(mainlayout)
gridlayout = QGridLayout()
gridlayout.addWidget(sectiontypegroupbox,1,0)
gridlayout.setContentsMargins(25,25,25,25)
self.setLayout(gridlayout)
def One(self):
print('One')
def Two(self):
print('Two')
def Three(self):
print('Three')
class FooWidget(QtWidgets.QWidget):
def __init__(self, path_icon, text, checked=False, parent=None):
super(FooWidget, self).__init__(parent)
lay = QtWidgets.QVBoxLayout(self)
pixmap = QtGui.QPixmap(os.path.join(iconroot, path_icon))
pixmap_label = QtWidgets.QLabel()
pixmap_label.resize(150, 150)
pixmap_label.setPixmap(pixmap.scaled(pixmap_label.size(), QtCore.Qt.KeepAspectRatio))
text_label = QtWidgets.QLabel(text)
checkbox = QtWidgets.QCheckBox(checked=checked)
lay.addWidget(pixmap_label)
lay.addWidget(text_label)
lay.addWidget(checkbox)
class Grid(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Grid, self).__init__(parent)
self.setFixedSize(self.sizeHint())
font = QFont("Georgia",8,QFont.Normal)
lay = QtWidgets.QHBoxLayout(self)
icons = ["images/fixed-fixed.png",
"images/pinned-pinned.png",
"images/fixed-free.png",
"images/fixed-pinned.png"]
texts = ["Ley = 1.0 L\nLec = 1.0 L",
"Ley = 0.699 L\nLec = 0.699 L",
"Ley = 2.0 L\nLec = 2.0 L",
"Ley = 0.5 L\nLec = 0.5 L"]
for path_icon, text in zip(icons, texts):
w = FooWidget(os.path.join(iconroot, path_icon), text)
lay.addWidget(w)
class thirdtabloads(QtWidgets.QWidget):
def __init__(self, parent=None):
super(thirdtabloads, self).__init__(parent)
self.adjustSize()
table = loadtable()
add_button = QtWidgets.QPushButton("Add")
add_button.clicked.connect(table._addrow)
delete_button = QtWidgets.QPushButton("Delete")
delete_button.clicked.connect(table._removerow)
copy_button = QtWidgets.QPushButton("Copy")
copy_button.clicked.connect(table._copyrow)
button_layout = QtWidgets.QVBoxLayout()
button_layout.addWidget(add_button, alignment=QtCore.Qt.AlignBottom)
button_layout.addWidget(delete_button, alignment=QtCore.Qt.AlignTop)
button_layout.addWidget(copy_button, alignment=QtCore.Qt.AlignTop )
tablehbox = QtWidgets.QHBoxLayout()
tablehbox.setContentsMargins(10,10,10,10)
tablehbox.addWidget(table)
grid = QtWidgets.QGridLayout(self)
grid.addLayout(button_layout, 0, 1)
grid.addLayout(tablehbox, 0, 0)
def copy_widget(w):
if isinstance(w, QtWidgets.QWidget):
new_w = type(w)()
if isinstance(w, QtWidgets.QComboBox):
vals = [w.itemText(ix) for ix in range(w.count())]
new_w.addItems(vals)
return new_w
class loadtable(QtWidgets.QTableWidget):
def __init__(self, parent=None):
super(loadtable, self).__init__(1, 5, parent)
self.setFont(QtGui.QFont("Helvetica", 10, QtGui.QFont.Normal, italic=False))
headertitle = ("Load Name","N [kN]","My [kNm]","Mz [kNm]","Load Type")
self.setHorizontalHeaderLabels(headertitle)
self.verticalHeader().hide()
self.horizontalHeader().setHighlightSections(False)
self.horizontalHeader().setSectionResizeMode(QtWidgets.QHeaderView.Fixed)
self.setSelectionMode(QtWidgets.QAbstractItemView.NoSelection)
self.setColumnWidth(0, 130)
combox_lay = QtWidgets.QComboBox(self)
combox_lay.addItems(["ULS","SLS"])
self.setCellWidget(0, 4, combox_lay)
self.cellChanged.connect(self._cellclicked)
#QtCore.pyqtSlot(int, int)
def _cellclicked(self, r, c):
it = self.item(r, c)
it.setTextAlignment(QtCore.Qt.AlignCenter)
#QtCore.pyqtSlot()
def _addrow(self):
rowcount = self.rowCount()
self.insertRow(rowcount)
combox_add = QtWidgets.QComboBox(self)
combox_add.addItems(["ULS","SLS"])
self.setCellWidget(rowcount, 4, combox_add)
#QtCore.pyqtSlot()
def _removerow(self):
if self.rowCount() > 0:
self.removeRow(self.rowCount()-1)
#QtCore.pyqtSlot()
def _copyrow(self):
r = self.currentRow()
if 0 <= r < self.rowCount():
cells = {"items": [], "widgets": []}
for i in range(self.columnCount()):
it = self.item(r, i)
if it:
cells["items"].append((i, it.clone()))
w = self.cellWidget(r, i)
if w:
cells["widgets"].append((i, copy_widget(w)))
self.copy(cells, r+1)
def copy(self, cells, r):
self.insertRow(r)
for i, it in cells["items"]:
self.setItem(r, i, it)
for i, w in cells["widgets"]:
self.setCellWidget(r, i, w)
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
app.setStyle("Fusion")
mainWin = mywindow()
mainWin.show()
mainWin.showMaximized()
sys.exit(app.exec_())
I would appreciate much any help on this.
If floating windows aren't essential to your tool then you can try dropping QDockWidget and using a series of QSplitter instead. This way you can have your nice box layout while having tabs to resize horizontally and vertically, and still resizing properly when the tool as a whole resizes.
My example is in PySide2, but you'll probably need to do very minor tweaks to PyQt5 (probably just the import names):
from PySide2 import QtCore
from PySide2 import QtGui
from PySide2 import QtWidgets
class SubWindow(QtWidgets.QWidget):
def __init__(self, label, parent=None):
super(SubWindow, self).__init__(parent)
self.label = QtWidgets.QLabel(label, parent=self)
self.label.setAlignment(QtCore.Qt.AlignCenter)
self.label.setStyleSheet("QLabel {font-size:40px;}")
self.main_layout = QtWidgets.QVBoxLayout()
self.main_layout.addWidget(self.label)
self.setLayout(self.main_layout)
class MainWindow(QtWidgets.QWidget):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.sub_win_1 = SubWindow("1", parent=self)
self.sub_win_2 = SubWindow("2", parent=self)
self.sub_win_3 = SubWindow("3", parent=self)
self.sub_win_4 = SubWindow("4", parent=self)
self.sub_splitter_1 = QtWidgets.QSplitter(QtCore.Qt.Horizontal, parent=self)
self.sub_splitter_1.addWidget(self.sub_win_1)
self.sub_splitter_1.addWidget(self.sub_win_2)
self.sub_splitter_2 = QtWidgets.QSplitter(QtCore.Qt.Horizontal, parent=self)
self.sub_splitter_2.addWidget(self.sub_win_3)
self.sub_splitter_2.addWidget(self.sub_win_4)
self.splitter = QtWidgets.QSplitter(QtCore.Qt.Vertical, parent=self)
self.splitter.addWidget(self.sub_splitter_1)
self.splitter.addWidget(self.sub_splitter_2)
self.main_layout = QtWidgets.QVBoxLayout()
self.main_layout.addWidget(self.splitter)
self.setLayout(self.main_layout)
self.setWindowTitle("Layout example")
self.resize(500, 500)
inst = MainWindow()
inst.show()
This gives you something like this:
Right now the top/bottom horizontal splitters function separately, but you can easily tie them together with an event.
Hope that helps!

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_())

QT QButtonGroup.checkedId() returns only one checked button

I created a QButtonGroup (there might be unused artefacts in the code. Please ignore them). I would like to retrieve the Id of all checked radio buttons. However, the QButtonGroup.checkedId() does return only one button at a time.
Is it possible to retrieve a list of all checked RadioButtons ?
import sys
from PyQt5.QtWidgets import QMainWindow, QApplication, QPushButton, QWidget, QAction, QTabWidget, QVBoxLayout,\
QHBoxLayout, QGridLayout, QSplitter, QFrame, QTextEdit, QFileDialog, QGroupBox,\
QButtonGroup, QLabel, QRadioButton
class MyRadioButtonGroup(QWidget):
"""
creates radio buttons from a list
"""
def __init__(self, label, instructions, name_list):
super().__init__()
self.title_label = QLabel(label)
self.name_list = name_list
# create the widget
self.layout = QVBoxLayout()
self.group_box = QGroupBox(instructions)
self.button_group = QButtonGroup()
self.button_group.setExclusive(False)
# create the buttons
self.button_list = [QRadioButton(item) for item in self.name_list]
self.button_layout = QVBoxLayout()
for i, button in enumerate(self.button_list):
self.button_layout.addWidget(button)
self.button_group.addButton(button)
self.button_group.setId(button, i)
self.group_box.setLayout(self.button_layout)
# create the main layout
self.main_layout = QVBoxLayout()
self.main_layout.addWidget(self.title_label)
self.main_layout.addWidget(self.group_box)
self.setLayout(self.main_layout)
# method for getting the state of the buttons
def get_states(self):
states = self.button_group.checkedId()
return states
class MainApp(QMainWindow):
""" This creates the main Window and configures its look
"""
def __init__(self):
'''
Initializes the class with standard parameters
'''
super().__init__()
self.title = 'Data Analysis App'
# start at top left corner of the screen
self.left = 0
self.top = 0
# set the window height and width
self.width = 1280
self.height = 780
# set the styles of fonts etc.
self.setStyleSheet('font-size: 16pt')
# call the makeUI method
self.makeUI()
def makeUI(self):
# set window geometry
self.setWindowTitle(self.title)
self.setGeometry(self.left, self.top, self.width, self.height)
# generate the tab layout
self.table_widget = MyTableWidget()
self.setCentralWidget(self.table_widget)
# apparently we have to call the show method in order to show it
self.show()
class MyTableWidget(QWidget):
"""
Initializes the tab layout
"""
def __init__(self):
super().__init__()
self.layout = QVBoxLayout(self)
# initialize the tab screens
self.tabs = QTabWidget()
# add the tab screens to the tab widget
self.tabs.resize(600, 600)
# make the layout of the tabs
self.make_tab1()
# initialize the tabs
self.layout.addWidget(self.tabs)
self.setLayout(self.layout)
def make_tab1(self):
"""Style of tab 1 is created here"""
'''Defines master layout of tab1'''
tab1 = QWidget()
tab1.layout = QHBoxLayout()
'''Button Section'''
# converts the data into excel and pandas dataframe
btn_test = QPushButton('Test')
btn_test.clicked.connect(self.test)
name_list = ['A', 'B', 'C']
self.radio_buttons = MyRadioButtonGroup('TEST', 'Check more than one', name_list)
'''Page layout section '''
tab1.layout.addWidget(btn_test)
tab1.layout.addWidget(self.radio_buttons)
tab1.setLayout(tab1.layout)
self.tabs.addTab(tab1, 'Test Radio Buttons')
''' Methods section
'''
def test(self):
print(self.radio_buttons.get_states())
if __name__ == '__main__':
""" This code block is always the same and makes sure that e.g. STRG+C kills the window etc.
"""
app = QApplication(sys.argv)
ex = MainApp()
sys.exit(app.exec())
You could just retrieve them with a list comprehension:
def test(self):
print([i for i, button in enumerate(self.radio_buttons.button_group.buttons()) if button.isChecked()])

Categories

Resources