I'm making a GUI in PyQt5 where there are multiple tabs. In one of the tabs, users select a radio button with what type of data they are entering.
This information changes what buttons are available in other tabs and I'm having trouble getting this information passed from the original tab class. I'd like to see if a radio button is checked from another tab and if it is, enable a button.
I have a function to return a string depending on which radio button is selected, but when I call the getDataType() function from the other tab, I get the error "AttributeError: module 'DataTab' has no attribute 'getDataType.'"
I've tried moving the getDataType() function outside of the DataTab class, but since the radio buttons use "self," I'm not able to access them.
I've also tried making a new class and calling that new class from the function, but then I get stuck on how to get the information to my other tab.
So in this example, once a user selects a radio button in the Data Tab, I want the corresponding push button on the Analysis Tab enabled.
When I uncomment the call to getDataType(), I get the following error: "AttributeError: module 'DataTab' has no attribute 'getDataType'"
from PyQt5.QtWidgets import (QWidget, QVBoxLayout, QLabel, QTableWidget, QTableWidgetItem,
QLineEdit, QFileDialog, QRadioButton, QGroupBox, QPushButton,
QGridLayout, QButtonGroup, QApplication, QAbstractItemView,
QTabWidget)
from PyQt5.QtGui import QIcon
import sys, os
class TabPage(QTabWidget):
def __init__(self):
super().__init__()
self.setStyleSheet('font: 15pt Tw Cen MT')
self.show()
# Creating the tabs here to have a reference
self.tabWidget = QTabWidget()
self.tabWidget.addTab(DataTab(), "Data Input")
self.tabWidget.addTab(AnalysisTab(), "Analysis")
self.layout = QVBoxLayout()
self.layout.addWidget(self.tabWidget)
self.setLayout(self.layout)
# The DataTab class holds all the GUI for the DataTab
class DataTab(QWidget):
def __init__(self):
super().__init__()
self.app = QApplication(sys.argv)
self.layout = QGridLayout()
self.intervalRadioButton = QRadioButton("Interval")
self.ordinalRadioButton = QRadioButton("Ordinal")
self.frequencyRadioButton = QRadioButton("Frequency")
self.submitButton = QPushButton("Submit Data")
self.layout.addWidget(self.intervalRadioButton, 7, 0, 1, 3)
self.layout.addWidget(self.ordinalRadioButton, 8, 0, 1, 3)
self.layout.addWidget(self.frequencyRadioButton, 9, 0, 1, 3)
self.setLayout(self.layout)
self.show()
def getDataType(self):
if self.intervalRadioButton.isChecked():
return "interval"
elif self.ordinalRadioButton.isChecked():
return "ordinal"
elif self.frequencyRadioButton.isChecked():
return "frequency"
class AnalysisTab(QWidget):
def __init__(self):
super().__init__()
self.app = QApplication(sys.argv)
self.createChooseIntervalGroup()
self.createChooseOrdinalGroup()
self.createChooseFrequencyGroup()
self.layout = QGridLayout()
self.layout.addWidget(self.ChooseIntervalGroup, 0, 1)
self.layout.addWidget(self.ChooseOrdinalGroup, 1, 1)
self.layout.addWidget(self.ChooseFrequencyGroup, 2, 1)
self.setLayout(self.layout)
self.show()
# The right side of AnalysisTab containing the buttons for
# analysis
def createChooseIntervalGroup(self):
self.ChooseIntervalGroup = QGroupBox("Tests for Interval Data")
self.analyzeIntervalButton = QPushButton("Analyze")
self.analyzeIntervalButton.setEnabled(False)
# if DataTab.getDataType() != "interval":
# self.analyzeIntervalButton.setEnabled(True)
self.layout = QGridLayout()
self.layout.addWidget(self.analyzeIntervalButton, 1, 1)
self.ChooseIntervalGroup.setLayout(self.layout)
# The right side of AnalysisTab containing the buttons for
# analysis
def createChooseOrdinalGroup(self):
self.ChooseOrdinalGroup = QGroupBox("Tests for Ordinal Data")
self.analyzeOrdinalButton = QPushButton("Analyze")
self.analyzeOrdinalButton.setEnabled(False)
# if DataTab.getDataType() != "ordinal":
# self.analyzeIntervalButton.setEnabled(True)
self.layout = QGridLayout()
self.layout.addWidget(self.analyzeOrdinalButton, 1, 1)
self.ChooseOrdinalGroup.setLayout(self.layout)
# The right side of AnalysisTab containing the buttons for
# analysis
def createChooseFrequencyGroup(self):
self.ChooseFrequencyGroup = QGroupBox("Tests for Frequency Data")
self.analyzeFrequencyButton = QPushButton("Analyze")
self.analyzeFrequencyButton.setEnabled(False)
# if DataTab.getDataType() != "frequency":
# self.analyzeIntervalButton.setEnabled(True)
self.layout = QGridLayout()
self.layout.addWidget(self.analyzeFrequencyButton, 1, 1)
self.ChooseFrequencyGroup.setLayout(self.layout)
def run():
app = QApplication(sys.argv)
tabPage = TabPage()
tabPage.show()
app.exec_()
run()
A possible solution for this case is to use the signals to notify the change of status of the QRadioButton to enable or disable the button.
import sys
from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import (
QWidget,
QVBoxLayout,
QRadioButton,
QGroupBox,
QPushButton,
QGridLayout,
QButtonGroup,
QApplication,
QTabWidget,
)
class Widget(QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.setStyleSheet("font: 15pt Tw Cen MT")
self.data_tab = DataTab()
self.analysis_tab = AnalysisTab()
self.tabWidget = QTabWidget()
self.tabWidget.addTab(self.data_tab, "Data Input")
self.tabWidget.addTab(self.analysis_tab, "Analysis")
layout = QVBoxLayout(self)
layout.addWidget(self.tabWidget)
self.data_tab.intervalRadioButton.toggled.connect(
self.analysis_tab.analyzeIntervalButton.setEnabled
)
self.data_tab.ordinalRadioButton.toggled.connect(
self.analysis_tab.analyzeOrdinalButton.setEnabled
)
self.data_tab.frequencyRadioButton.toggled.connect(
self.analysis_tab.analyzeFrequencyButton.setEnabled
)
class DataTab(QWidget):
def __init__(self, parent=None):
super().__init__(parent)
layout = QGridLayout(self)
self.intervalRadioButton = QRadioButton("Interval")
self.ordinalRadioButton = QRadioButton("Ordinal")
self.frequencyRadioButton = QRadioButton("Frequency")
self.submitButton = QPushButton("Submit Data")
layout.addWidget(self.intervalRadioButton, 7, 0, 1, 3)
layout.addWidget(self.ordinalRadioButton, 8, 0, 1, 3)
layout.addWidget(self.frequencyRadioButton, 9, 0, 1, 3)
class AnalysisTab(QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.createChooseIntervalGroup()
self.createChooseOrdinalGroup()
self.createChooseFrequencyGroup()
layout = QGridLayout(self)
layout.addWidget(self.ChooseIntervalGroup, 0, 1)
layout.addWidget(self.ChooseOrdinalGroup, 1, 1)
layout.addWidget(self.ChooseFrequencyGroup, 2, 1)
def createChooseIntervalGroup(self):
self.ChooseIntervalGroup = QGroupBox("Tests for Interval Data")
self.analyzeIntervalButton = QPushButton("Analyze")
self.analyzeIntervalButton.setEnabled(False)
layout = QGridLayout(self.ChooseIntervalGroup)
layout.addWidget(self.analyzeIntervalButton, 1, 1)
def createChooseOrdinalGroup(self):
self.ChooseOrdinalGroup = QGroupBox("Tests for Ordinal Data")
self.analyzeOrdinalButton = QPushButton("Analyze")
self.analyzeOrdinalButton.setEnabled(False)
layout = QGridLayout(self.ChooseOrdinalGroup)
layout.addWidget(self.analyzeOrdinalButton, 1, 1)
def createChooseFrequencyGroup(self):
self.ChooseFrequencyGroup = QGroupBox("Tests for Frequency Data")
self.analyzeFrequencyButton = QPushButton("Analyze")
self.analyzeFrequencyButton.setEnabled(False)
layout = QGridLayout(self.ChooseFrequencyGroup)
layout.addWidget(self.analyzeFrequencyButton, 1, 1)
def run():
app = QApplication(sys.argv)
tabPage = Widget()
tabPage.show()
app.exec_()
run()
Related
I am trying to make a programmable sequencer where I can configure objects that I've programmed and create a list of them to run. That requires me to instantiate that object by defining it's properties and I'd like to make a tab control on the blue widget shown below that has an inputs and outputs tab.
Anytime I try to implement this, it replaces all of the other widgets:
Surely that has to be a way to use a standard tab control in a widget right?
Code below:
import sys
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QApplication, QGridLayout, QLabel, QMainWindow, QWidget, QTabWidget, QVBoxLayout
from PyQt5.QtGui import QColor, QPalette
# Placeholder widget for setting up layout
class Color(QWidget):
def __init__(self, color):
super().__init__()
self.setAutoFillBackground(True)
palette = self.palette()
palette.setColor(QPalette.Window, QColor(color))
self.setPalette(palette)
# Creating tab widgets
class MyTabWidget(QTabWidget):
def __init__(self):
super().__init__()
self.setTabPosition(QTabWidget.North)
for n, color in enumerate(['blue', 'purple']):
self.addTab(Color(color), color)
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("My App")
layout = QGridLayout()
# 1
layout.addWidget(Color("red"), 0, 0, 2, 1)
# 2
layout.addWidget(Color("yellow"), 2, 0, 3, 1)
# 3
layout.addWidget(Color("green"), 0, 1, 5, 4)
# 4
# layout.addWidget(Color("blue"), 0, 5, 5, 1)
tabs = MyTabWidget()
layout.addWidget(tabs, 0, 5, 5, 1)
widget = QWidget()
widget.setLayout(layout)
self.setCentralWidget(widget)
app = QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec_()
The size policy of the QTabWidget is set to stretch and since the stretch factors of the QGridLayout items is 0 then it will cause the items to be compressed. The solution is to set the stretch factors to 1:
widget = QWidget()
widget.setLayout(layout)
self.setCentralWidget(widget)
for column in range(layout.columnCount()):
layout.setColumnStretch(column, 1)
for row in range(layout.rowCount()):
layout.setRowStretch(row, 1)
I need to have ability to create endless widgets by .addWidget (in grid, new widget - new row). I already have it. But im also need ability to delete widgets by his position. I tried this:
from PyQt5 import QtWidgets, QtGui
from PyQt5.QtCore import QTime, QTimer, QObject
from PyQt5.QtWidgets import QMainWindow, QApplication, QLCDNumber, QPushButton, QGridLayout, QLabel, QLineEdit, QTextEdit, QGroupBox
import sys
from somethingtestui import Ui_MainWindow
global selection
selection = 1
class mywindow(QtWidgets.QMainWindow):
def __init__(self):
super(mywindow, self).__init__()
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
self.ui.pushButton.clicked.connect(self.add)
def add(self):
global selection
self.row = QTextEdit('')
self.text3 = QPushButton('Delete row')
self.ui.gridLayout.addWidget(self.row, selection, 0, 1, 1)
self.ui.gridLayout.addWidget(self.text3, selection, 1, 1, 1)
# global delf
def delf():
global selection
selection = selection-1
number = self.ui.gridLayout.itemAtPosition(selection,1)
print(number)
self.row.deleteLater()
self.rrow = None
self.text3.deleteLater()
self.text3 = None
self.text3.clicked.connect(delf)
selection = selection+1
app = QtWidgets.QApplication([])
application = mywindow()
application.show()
sys.exit(app.exec())
With it i can add many widgets. If there are one created widget i am free to delete it and repeat it. But if there are 2 or more created widget i can delete one of them, and after click button "Delete" in the other row it crash:
Traceback (most recent call last):
File "E:\Programs\YandexDisk\Tempfiles\TournamentBot\testi22.py", line 31, in delf
self.row.deleteLater()
RuntimeError: wrapped C/C++ object of type QTextEdit has been deleted
I found solution for myself
from somethingtestui import Ui_MainWindow
global rowcnt
rowcnt = 1
class mywindow(QtWidgets.QMainWindow):
def __init__(self):
super(mywindow, self).__init__()
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
self.ui.pushButton.clicked.connect(self.add)
self.ui.gridLayout.setRowMinimumHeight(50,50)
self.ui.gridLayout.setColumnMinimumWidth(50,50)
def add(self):
global rowcnt
self.row = QTextEdit('')
self.delbtn = QPushButton('Delete row')
self.ui.gridLayout.addWidget(self.row, rowcnt, 0, 1, 1)
self.ui.gridLayout.addWidget(self.delbtn, rowcnt, 1, 1, 1)
w = self.ui.gridLayout.itemAtPosition(rowcnt,1).widget()
def delf(currow):
global rowcnt
rowcnt = rowcnt-1
number = self.ui.gridLayout.itemAtPosition(currow,1).widget()
number2 = self.ui.gridLayout.itemAtPosition(currow,0).widget()
number.deleteLater()
number2.deleteLater()
w.clicked.connect(lambda: delf(mrowcnt))
rowcnt = rowcnt+1
mrowcnt = rowcnt-1
I'm trying to get the player's names and the color that they choose for a next step in the project. Getting the names is easy enough but the colors is a bit of a pain.
I don't know how to get the selected color and apply it the button using the QColorDialog. The ultimate goal is to get a structure with player name linked to the color they chose.
Here is what i have:
from PyQt5.QtWidgets import (
QLineEdit,
QWidget,
QApplication,
QLabel,
QMainWindow,
QGridLayout,
QColorDialog,
QPushButton,
QVBoxLayout,
QHBoxLayout,
)
import sys
class NamesPlayers(QMainWindow):
""" name screen, ask the names of the players """
def __init__(self, nb_players):
super().__init__()
self.layout_widget = QWidget()
self.player_names = []
self.player_colors = []
main_layout = QVBoxLayout()
names_layout = QGridLayout()
button_layout = QHBoxLayout()
button_list = []
for i in range(nb_players):
label = QLabel("Name :")
player_name = QLineEdit()
color_button = QPushButton("Color")
color_button.setStyleSheet("background-color: white")
names_layout.addWidget(label, i, 0)
names_layout.addWidget(player_name, i, 1)
names_layout.addWidget(color_button, i, 2)
button_list.append(color_button)
self.player_names.append(player_name)
self.player_colors.append(color_button.styleSheet())
self.confirm_button = QPushButton("Confirm")
button_layout.addWidget(self.confirm_button)
main_layout.addLayout(names_layout)
main_layout.addLayout(button_layout)
for button in button_list:
button.clicked.connect(self.open_colordialog)
self.layout_widget.setLayout(main_layout)
self.setCentralWidget(self.layout_widget)
def open_colordialog(self):
color_dialog = QColorDialog()
color_dialog.exec_()
if __name__ == "__main__":
app = QApplication(sys.argv)
window = NamesPlayers(4)
window.show()
app.exec_()
My main issue i guess is the fact that the number of buttons for the color can vary and when I click on those buttons, the address for the QColorDialog is always the same which is not what I want.
Any help is appreciated
One possible solution is to use the sender() method to get the button pressed:
import sys
from PyQt5 import QtCore, QtWidgets
class NamesPlayers(QtWidgets.QMainWindow):
""" name screen, ask the names of the players """
def __init__(self, nb_players, parent=None):
super().__init__(parent)
names_layout = QtWidgets.QGridLayout()
for i in range(nb_players):
label = QtWidgets.QLabel("Name :")
player_name = QtWidgets.QLineEdit()
color_button = QtWidgets.QPushButton("Color")
color_button.setStyleSheet("background-color: white")
color_button.clicked.connect(self.open_colordialog)
names_layout.addWidget(label, i, 0)
names_layout.addWidget(player_name, i, 1)
names_layout.addWidget(color_button, i, 2)
self.confirm_button = QtWidgets.QPushButton("Confirm")
central_widget = QtWidgets.QWidget()
main_layout = QtWidgets.QVBoxLayout(central_widget)
button_layout = QtWidgets.QHBoxLayout()
button_layout.addWidget(self.confirm_button)
main_layout.addLayout(names_layout)
main_layout.addLayout(button_layout)
self.setCentralWidget(central_widget)
#QtCore.pyqtSlot()
def open_colordialog(self):
button = self.sender()
color_dialog = QtWidgets.QColorDialog()
if color_dialog.exec_() == QtWidgets.QColorDialog.Accepted:
button.setStyleSheet(
"background-color: {}".format(color_dialog.selectedColor().name())
)
button.clearFocus()
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
window = NamesPlayers(4)
window.show()
sys.exit(app.exec_())
Another possible solution is to send the button pressed (with the methods indicated in this answer):
from functools import partial
# ...
for i in range(nb_players):
# ...
color_button = QtWidgets.QPushButton("Color")
color_button.setStyleSheet("background-color: white")
color_button.clicked.connect(partial(self.open_colordialog, color_button))
# or
# color_button.clicked.connect(lambda *args, btn=color_button: self.open_colordialog(btn))
def open_colordialog(self, button):
color_dialog = QtWidgets.QColorDialog()
if color_dialog.exec_() == QtWidgets.QColorDialog.Accepted:
button.setStyleSheet(
"background-color: {}".format(color_dialog.selectedColor().name())
)
button.clearFocus()
I need to get the table row index during a contextMenuEvent in pyQt5, but I keep getting odd row offsets. Since this is my first pyQt project, I'm quite lost. I have the following code.
def contextMenuEvent(self, event):
menu = QMenu(self)
openAction = menu.addAction('Open in browser')
action = menu.exec_(event.globalPos())
if action == openAction:
row = self.tableWidget.rowAt(event.y()) # Should this be event.globalY?
self.so_something(row)
Edit: adding code sample. You can see that when the execution gets to the event produced when right-clicking on a row, the printed number is not the correct row number. Usually it has an offset, and last rows produce -1.
import sys
from PyQt5.QtCore import Qt, QSize
from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import QLabel, QLineEdit, QWidget, \
QPushButton, QVBoxLayout, QHBoxLayout, QComboBox, \
QTableWidget, QHeaderView, QTableWidgetItem, \
QMenu, QApplication
class MainWindow(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
# Window size and title
self.setWindowTitle('Test')
self.resize(700, 700)
self.setMinimumWidth(700)
# Label
addressLabel = QLabel('Testing')
addressLabel.setAlignment(Qt.AlignCenter)
# Dropdown
self.addressDropdown = QComboBox(self)
self.addressDropdown.addItem('A')
self.addressDropdown.addItem('B')
# Refresh button
refreshButton = QPushButton()
refreshButton.setMaximumSize(40, 40)
# Address layout
addressayout = QHBoxLayout()
addressayout.addWidget(addressLabel, 1)
addressayout.addWidget(self.addressDropdown, 7)
addressayout.addWidget(refreshButton)
# Balance label
balaceLabel = QLabel()
balaceLabel.setText('Testing')
balaceLabel.setAlignment(Qt.AlignCenter)
# Balance amount label
self.balaceAmountLabel = QLabel()
self.balaceAmountLabel.setText('Testing')
self.balaceAmountLabel.setAlignment(Qt.AlignCenter)
# Balance layout
balanceLayout = QVBoxLayout()
balanceLayout.addWidget(balaceLabel)
balanceLayout.addWidget(self.balaceAmountLabel)
# Transactions label
transactionsLabel = QLabel('Testing')
transactionsLabel.setAlignment(Qt.AlignCenter)
# Transactions table
self.tableWidget = QTableWidget()
self.tableWidget.setRowCount(10)
self.tableWidget.setColumnCount(1)
self.tableWidget.verticalHeader().setVisible(False)
self.tableWidget.horizontalHeader().setVisible(False)
self.tableWidget.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
self.tableWidget.horizontalHeader().setSectionResizeMode(0, QHeaderView.Stretch)
item = QTableWidgetItem('Testing')
item.setTextAlignment(Qt.AlignVCenter | Qt.AlignHCenter)
self.tableWidget.setItem(0, 0, item)
# Transactions layout
transactionsLayout = QVBoxLayout()
transactionsLayout.addWidget(transactionsLabel)
transactionsLayout.addWidget(self.tableWidget)
# Send label A
sendLabelA = QLabel('Send')
sendLabelA.setAlignment(Qt.AlignCenter)
# Send amount
self.sendAmount = QLineEdit()
self.sendAmount.setAlignment(Qt.AlignCenter)
# Send label B
sendLabelB = QLabel('to')
sendLabelB.setAlignment(Qt.AlignCenter)
# Send address
self.sendAddress = QLineEdit()
self.sendAddress.setAlignment(Qt.AlignCenter)
# Send button
sendButton = QPushButton()
sendButton.setMaximumSize(40, 40)
sendIcon = QIcon.fromTheme("mail-send")
sendButton.setIcon(sendIcon)
sendButton.setIconSize(QSize(24,24))
# Send layout
sendLayout = QHBoxLayout()
sendLayout.addWidget(sendLabelA)
sendLayout.addWidget(self.sendAmount, 2)
sendLayout.addWidget(sendLabelB)
sendLayout.addWidget(self.sendAddress, 4)
sendLayout.addWidget(sendButton)
# Window layout
layout = QVBoxLayout()
layout.addLayout(addressayout)
layout.addLayout(balanceLayout)
layout.addLayout(transactionsLayout)
layout.addLayout(sendLayout)
self.setLayout(layout)
def contextMenuEvent(self, event):
menu = QMenu(self)
openAction = menu.addAction('Open in browser')
action = menu.exec_(event.globalPos())
row = self.tableWidget.rowAt(event.y())
if action == openAction:
print(row)
if __name__ == '__main__':
app = QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec_()
The coordinate that rowAt() method requires must be with respect to the viewport of the QTableWidget so you must convert the global position to local using mapFromGlobal() method:
def contextMenuEvent(self, event):
gp = event.globalPos()
menu = QMenu(self)
openAction = menu.addAction("Open in browser")
action = menu.exec_(gp)
vp_pos = self.tableWidget.viewport().mapFromGlobal(gp)
row = self.tableWidget.rowAt(vp_pos.y())
if action == openAction:
print(row)
I have been studying PyQt5 and recenlty decided to make a gui for a simple chat client. This is my mockup:
I used QGridLayout, and this is what I got:
How do I decrease the size of the bottom QTextEdit, so it has 2-3 available lines, and make QPushButton larger?
My program:
import sys
from PyQt5.QtWidgets import (QMainWindow, QAction, QApplication, QDesktopWidget,
QDialog, QTextEdit, QGridLayout, QPushButton, QWidget)
from PyQt5.QtGui import QIcon
class Chat(QMainWindow):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.populateUI()
self.resize(400, 400)
self.center()
self.setWindowTitle('Simple Chat')
self.show()
def center(self):
qr = self.frameGeometry()
cp = QDesktopWidget().availableGeometry().center()
qr.moveCenter(cp)
self.move(qr.topLeft())
def populateUI(self):
self.createMenu()
self.statusBar()
centralWidget = CentralWidget()
self.setCentralWidget(centralWidget)
def createMenu(self):
menuBar = self.menuBar()
fileMenu = menuBar.addMenu('&File')
fileMenu.addAction(self.createExitAction())
helpMenu = menuBar.addMenu('&Help')
helpMenu.addAction(self.createAboutAction())
def createExitAction(self):
exitAction = QAction(QIcon('exit.png'), '&Exit', self)
exitAction.setShortcut('Ctrl+Q')
exitAction.setStatusTip('Exit application')
exitAction.triggered.connect(self.close)
return exitAction
def createAboutAction(self):
aboutAction = QAction(QIcon('info.png'), '&About', self)
aboutAction.setShortcut('Ctrl+H')
aboutAction.setStatusTip('Information about the program')
aboutAction.triggered.connect(self.createAboutDialog)
return aboutAction
def createAboutDialog(self):
dialog = QDialog(self)
dialog.setWindowTitle('About')
dialog.setWindowIcon(QIcon('info.png'))
dialog.resize(200, 200)
dialog.exec_()
class CentralWidget(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
ribbon = QTextEdit()
chat = QTextEdit()
sendBtn = QPushButton('Send')
grid = QGridLayout()
grid.setSpacing(3)
grid.addWidget(ribbon, 0, 0, 1, 3)
grid.addWidget(chat, 1, 0, 1, 1)
grid.addWidget(sendBtn, 1, 2)
self.setLayout(grid)
if __name__ == '__main__':
app = QApplication(sys.argv)
chat = Chat()
sys.exit(app.exec_())
You first need to set a fixed height for the bottom text-edit based on the number of lines you want shown. This also needs to take account of the frame and document margin:
def initUI(self):
...
chat.setFixedHeight(
(chat.fontMetrics().lineSpacing() * 3) +
(chat.document().documentMargin() * 2) +
(chat.frameWidth() * 2) - 1
)
You then need to change the size policy of the button so that it expands vertically:
policy = sendBtn.sizePolicy()
policy.setVerticalPolicy(QSizePolicy.MinimumExpanding)
sendBtn.setSizePolicy(policy)
Finally, you need to set the stretch factors on the first row and column so that the text-edits take up all the available space:
grid.setRowStretch(0, 1)
grid.setColumnStretch(0, 1)
I guess you are looking after setFixedSize(QSize size) of QWidget.