Emiting QTableWidgetItem specific signal on being clicked - python

I want to implement the functionality that multiple QTableWidgetItems inside of a QTableWidget can be selected and unselected so that the values and "positions" of those QTableWidgetItems is known for further use.
Inside of the QTableWidget there are some empty cells, for aesthetics/spacing, which should be ignored by the functionality I'm trying to implement.
But that could also easily be done afterwards by checking if a selected item does have content.
self.table_widget.itemClicked.connect(self.some_function)
Would be the signal best fitting but I cannot specify or know which item was clicked inside of the table widget or whether is was selected or unselected.
Question: How do I implement the functionality to emit a specific signal when a specific QTableWidgetItem is pressed?
Here some pseude code for use in examples:
class Window(QtWidgets.QMainWindow):
def __init__(self):
super(Window, self).__init__()
uic.loadUi("qtdesignerfile.ui", self)
self.show()
#connect signal to function
self.table_widget.itemClicked.connect(self.some_function)
#create "global" list to save all selected items
self.selected_items = []
#some function to execute the logic
def some_function(self):
#condition distinguishing if item was just selected or unselected
if QTableWidgetItem(row, column) is not already selected:
#change background color to indicate selection
self.table_widget.item(row,column).setBackground(QtGui.QColor(100,100,100))
#"format" information of clicked item for further use
selected_item = [str(table_widget.item(row,column).text()), row, column]
#"save" selected item in global list for further use
self.selected_items.append(selected_item)
#condition distinguishing if item was just selected or unselected
if QTableWidgetItem(row, column) is already selected:
#change background color to indicate un-selection
self.table_widget.item(row,column).setBackground(QtGui.QColor(0,0,0))
#"format" information of clicked item for further use
selected_item = [str(table_widget.item(row,column).text()), row, column]
#remove the un-selected item from global list
self.selected_items.remove(selected_item)
Example ui-file:
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>418</width>
<height>297</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralwidget">
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QTableWidget" name="table_widget">
<row>
<property name="text">
<string>Row 1</string>
</property>
</row>
<row>
<property name="text">
<string>Row 2</string>
</property>
</row>
<row>
<property name="text">
<string>Row 3</string>
</property>
</row>
<row>
<property name="text">
<string>Row 4</string>
</property>
</row>
<row>
<property name="text">
<string>Row 5</string>
</property>
</row>
<row>
<property name="text">
<string>Row 6</string>
</property>
</row>
<column>
<property name="text">
<string>Grouping</string>
</property>
</column>
<column>
<property name="text">
<string>Column 2</string>
</property>
</column>
<column>
<property name="text">
<string>Column 3</string>
</property>
</column>
<item row="0" column="0">
<property name="text">
<string>category 1</string>
</property>
</item>
<item row="1" column="1">
<property name="text">
<string>Entry (1,1)</string>
</property>
</item>
<item row="1" column="2">
<property name="text">
<string>Entry(1,2)</string>
</property>
</item>
<item row="2" column="1">
<property name="text">
<string>Entry(2,1)</string>
</property>
</item>
<item row="2" column="2">
<property name="text">
<string>Entry(2,2)</string>
</property>
</item>
<item row="3" column="0">
<property name="text">
<string>category 2</string>
</property>
</item>
<item row="4" column="1">
<property name="text">
<string>Entry(4,1)</string>
</property>
</item>
<item row="4" column="2">
<property name="text">
<string>Entry(4,2)</string>
</property>
</item>
<item row="5" column="1">
<property name="text">
<string>Entry(5,1)</string>
</property>
</item>
<item row="5" column="2">
<property name="text">
<string>Entry(5,2)</string>
</property>
</item>
</widget>
</item>
</layout>
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>418</width>
<height>21</height>
</rect>
</property>
</widget>
<widget class="QStatusBar" name="statusbar"/>
</widget>
<resources/>
<connections/>
</ui>
I am really puzzled on how to easily implement this functionality and am open to suggestion on a different approach.
The user of the application should be able to select multiple QTableWidgetItems so that the information of the row the item is inside can be transferred to another QTableWidget for further use.

The itemClicked signal does pass the element that is pressed if the element exists, by default Qt Designer only creates elements in which it edited, where appropriate where it placed text.
from PyQt5 import QtCore, QtGui, QtWidgets, uic
SelectedRole = QtCore.Qt.UserRole + 1000
class Window(QtWidgets.QMainWindow):
def __init__(self):
super(Window, self).__init__()
uic.loadUi("qtdesignerfile.ui", self)
# self.tableWidget.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
self.tableWidget.itemClicked.connect(self.onClicked)
#QtCore.pyqtSlot(QtWidgets.QTableWidgetItem)
def onClicked(self, it):
state = not it.data(SelectedRole)
it.setData(SelectedRole, state)
it.setBackground(
QtGui.QColor(100, 100, 100) if state else QtGui.QColor(0, 0, 0)
)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = Window()
w.show()
sys.exit(app.exec_())

Related

How to call function when space key is pressed inside the lineEdit

I want to call a function that checks words count in a lineEdit whenever I press space key inside the lineEdit. But how can I do that. After executing the python file press 'Start Game' to go to the lineEdit. Thanks!
Here's my code:
from PyQt5.QtWidgets import QMainWindow, QApplication, QLabel, QLineEdit, QPushButton, QTextBrowser, QStackedWidget, QWidget, QLCDNumber, QComboBox
from PyQt5 import uic
import sys
from PyQt5.QtGui import QKeyEvent
from PyQt5.QtCore import QThread, pyqtSignal, Qt
import random
class UI(QMainWindow):
def __init__(self):
super(UI, self).__init__()
# Load the ui file
uic.loadUi("Typing_test_UI.ui", self)
# Define our widgets
self.textBrowser = self.findChild(QTextBrowser, "textBrowser")
self.lineEdit = self.findChild(QLineEdit, "lineEdit")
self.counter = self.findChild(QLCDNumber, "counter")
self.startBtn = self.findChild(QPushButton, "startBtn")
self.timeCombo = self.findChild(QComboBox, "timeCombo")
self.difficultyCombo = self.findChild(QComboBox, "difficultyCombo")
self.stackedWidget = self.findChild(QStackedWidget, "stackedWidget")
self.startPage = self.findChild(QWidget, "startPage")
self.gamePage = self.findChild(QWidget, "gamePage")
self.scorePage = self.findChild(QWidget, "scorePage")
self.highScoreLabel = self.findChild(QLabel, "highScoreLabel")
self.scoreLabel = self.findChild(QLabel, "scoreLabel")
self.retryBtn = self.findChild(QPushButton, "retryBtn")
self.space_count = 0
self.startBtn.clicked.connect(self.start_game)
self.retryBtn.clicked.connect(self.goto_home_page)
# Show the app
self.show()
def start_game(self):
self.stackedWidget.setCurrentWidget(self.gamePage)
self.textBrowser.clear()
with open("Typing_sentences.txt", "r") as f:
all_texts = f.readlines()
lines_of_text = len(all_texts)
self.textBrowser.append(all_texts[random.randint(0, lines_of_text-1)])
def goto_home_page(self):
self.stackedWidget.setCurrentWidget(self.startPage)
app = QApplication(sys.argv)
UIWindow = UI()
app.exec_()
The sentences for a function in my code:
He found himself sitting at his computer, typing whatever came to mind. He was on a website entitled 10 fast fingers. This site tested how fast you were at typing. So he typed. He was currently typing about himself typing, which is odd in a way. He was now describing about how he was typing about himself typing.
The Internet is the global system of interconnected computer networks that uses the Internet protocol suite to communicate between networks and devices. It is a network of networks that consists of private, public, academic, business, and government networks of local to global scope, linked by a broad array of electronic, wireless, and optical networking technologies. The Internet carries a vast range of information resources and services, such as the inter-linked hypertext documents and applications of the World Wide Web (WWW), electronic mail, telephony, and file sharing.
The ui file:
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>801</width>
<height>443</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>801</width>
<height>443</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>801</width>
<height>443</height>
</size>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralwidget">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QStackedWidget" name="stackedWidget">
<property name="currentIndex">
<number>2</number>
</property>
<widget class="QWidget" name="startPage">
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QWidget" name="widget_3" native="true">
<widget class="QComboBox" name="timeCombo">
<property name="geometry">
<rect>
<x>280</x>
<y>60</y>
<width>201</width>
<height>41</height>
</rect>
</property>
<property name="font">
<font>
<pointsize>11</pointsize>
</font>
</property>
<item>
<property name="text">
<string>1 Minute</string>
</property>
</item>
<item>
<property name="text">
<string>2 Minutes</string>
</property>
</item>
<item>
<property name="text">
<string>5 Minutes</string>
</property>
</item>
<item>
<property name="text">
<string>10 Minutes</string>
</property>
</item>
</widget>
<widget class="QComboBox" name="difficultyCombo">
<property name="geometry">
<rect>
<x>280</x>
<y>130</y>
<width>201</width>
<height>41</height>
</rect>
</property>
<property name="font">
<font>
<pointsize>12</pointsize>
</font>
</property>
<item>
<property name="text">
<string>Easy</string>
</property>
</item>
<item>
<property name="text">
<string>Medium</string>
</property>
</item>
<item>
<property name="text">
<string>Hard</string>
</property>
</item>
</widget>
<widget class="QPushButton" name="startBtn">
<property name="geometry">
<rect>
<x>230</x>
<y>230</y>
<width>301</width>
<height>61</height>
</rect>
</property>
<property name="font">
<font>
<pointsize>16</pointsize>
</font>
</property>
<property name="text">
<string>Start Game</string>
</property>
</widget>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="gamePage">
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0" alignment="Qt::AlignRight|Qt::AlignTop">
<widget class="QWidget" name="widget_2" native="true">
<property name="layoutDirection">
<enum>Qt::LeftToRight</enum>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<item alignment="Qt::AlignRight">
<widget class="QLCDNumber" name="counter">
<property name="minimumSize">
<size>
<width>150</width>
<height>30</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>150</width>
<height>16777215</height>
</size>
</property>
<property name="layoutDirection">
<enum>Qt::RightToLeft</enum>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="1" column="0">
<widget class="QWidget" name="widget" native="true">
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0" colspan="2">
<widget class="QTextBrowser" name="textBrowser"/>
</item>
<item row="1" column="0" colspan="2">
<widget class="QLineEdit" name="lineEdit">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>45</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>45</height>
</size>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="scorePage">
<widget class="QLabel" name="scoreLabel">
<property name="geometry">
<rect>
<x>240</x>
<y>90</y>
<width>300</width>
<height>71</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>300</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>100</height>
</size>
</property>
<property name="font">
<font>
<pointsize>20</pointsize>
</font>
</property>
<property name="text">
<string>Score: 0</string>
</property>
</widget>
<widget class="QPushButton" name="retryBtn">
<property name="geometry">
<rect>
<x>652</x>
<y>320</y>
<width>121</width>
<height>64</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>64</width>
<height>64</height>
</size>
</property>
<property name="text">
<string>Retry</string>
</property>
<property name="iconSize">
<size>
<width>64</width>
<height>64</height>
</size>
</property>
</widget>
<widget class="QLabel" name="highScoreLabel">
<property name="geometry">
<rect>
<x>291</x>
<y>185</y>
<width>200</width>
<height>18</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>200</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>50</height>
</size>
</property>
<property name="font">
<font>
<pointsize>9</pointsize>
</font>
</property>
<property name="text">
<string>High Score: 0</string>
</property>
</widget>
</widget>
</widget>
</item>
</layout>
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>801</width>
<height>26</height>
</rect>
</property>
<widget class="QMenu" name="menuPapers">
<property name="title">
<string>Options</string>
</property>
<widget class="QMenu" name="menuTest_papers">
<property name="title">
<string>Test papers</string>
</property>
<addaction name="actionRandom"/>
<addaction name="actionChoose"/>
</widget>
<addaction name="menuTest_papers"/>
<addaction name="actionReset"/>
</widget>
<addaction name="menuPapers"/>
</widget>
<action name="actionRandom">
<property name="text">
<string>Random</string>
</property>
</action>
<action name="actionChoose">
<property name="text">
<string>Choose</string>
</property>
</action>
<action name="actionReset">
<property name="text">
<string>Reset High Score</string>
</property>
</action>
</widget>
<resources/>
<connections/>
</ui>
Here is an example of installing an Event Filter on the QLineEdit as suggested. See the inline comments for details and explanation.
...
class UI(QMainWindow):
def __init__(self):
super(UI, self).__init__()
# Load the ui file
uic.loadUi("Typing_test_UI.ui", self)
# Define our widgets
...
...
self.spaceFilter = SpaceFilter(parent=self) # init filter
self.spaceFilter.spacePressed.connect(self.my_function) # connect to the signal
self.lineEdit.installEventFilter(self.spaceFilter) # install on lineedit
self.space_count = 0
self.startBtn.clicked.connect(self.start_game)
self.retryBtn.clicked.connect(self.goto_home_page)
# Show the app
self.show()
def my_function(self): # custom function that runs when space bar is
for i in range(5): # pressed while typing in the line edit
for i in range(1000):
print(str(i), end="\r")
def start_game(self):
self.stackedWidget.setCurrentWidget(self.gamePage)
self.textBrowser.clear()
with open("list1.txt", "r") as f:
all_texts = f.readlines()
lines_of_text = len(all_texts)
self.textBrowser.append(all_texts[random.randint(0, lines_of_text-1)])
def goto_home_page(self):
self.stackedWidget.setCurrentWidget(self.startPage)
class SpaceFilter(QObject): # the event filter object
spacePressed = pyqtSignal() # the signal emited when space bar detected
def eventFilter(self, widget, event):
if event.type() == QEvent.KeyPress: # listen for key press events
if event.key() == Qt.Key.Key_Space: # if the key is the space bar
self.spacePressed.emit() # emit the signal
return False

Unable to Resize Column Contents according to the values of the column

I have a table which is being populated by the Database (MySQL) at the backend.
I am trying to resize the Columns according to the contents of each column (as much the stretch is possible), however I can't seem to do it.
I looked it up on Stackoverflow and found that I can do it by setting the QScrollAbstractArea.sizeAdjustPolicy to AdjustToContents in the Qt Designer.
I did this but it still did not work.
I further looked it up and found different solutions. One of them was this as well but it also did not work for me,
self.ui.course_table.horizontalHeader().setSectionResizeMode(0, QtWidgets.QHeaderView.Stretch)
self.ui.course_table.horizontalHeader().setSectionResizeMode(1, QtWidgets.QHeaderView.ResizeToContents)
self.ui.course_table.horizontalHeader().setSectionResizeMode(2, QtWidgets.QHeaderView.ResizeToContents)
I have shared a picture of my current table right now and I want to expand each column according to the content I have.
As you can see, there is a lot of space that can be stretched but it is not doing it despite having enough space. Even the Column names are not fully visible and some characters are cut off
In not maximized window form, this is what I get
As for my data, it is coming from MySQL database and it is attached to Button Click (whenever I click on the "Courses" button on the side menu, it will populate the data on the table in the Courses Page)
The function that is populating the table is as follows,
def get_course_data(self):
mycursor = self.DB.cursor() # DB is an object of class
Subquery = "Select course_name, course_code, course_type from tbl_course"
mycursor.execute(Subquery)
numcols = len(mycursor.fetchall()[0])
mycursor.execute(Subquery)
numrows = len(mycursor.fetchall())
self.ui.course_table.setRowCount(numrows)
self.ui.course_table.setColumnCount(numcols+1)
mycursor.execute(Subquery)
tablerow = 0
for row in mycursor.fetchall():
tablecol = 0
layout = QHBoxLayout()
layout.setContentsMargins(0, 0, 0, 0)
layout.setSpacing(0)
delete_button = QPushButton()
icon_delete = QIcon()
icon_delete.addFile(u":/icons/icons/Delete-button.png", QSize(), QIcon.Normal, QIcon.Off)
delete_button.setIcon(icon_delete)
layout.addWidget(delete_button)
edit_button = QPushButton()
index = PySide2.QtCore.QPersistentModelIndex(self.ui.course_table.model().index(tablerow, tablecol))
edit_button.clicked.connect(lambda *args, index=index: self.on_course_edit_click())
icon_edit = QIcon()
icon_edit.addFile(u":/icons/icons/edit-button.png", QSize(), QIcon.Normal, QIcon.Off)
edit_button.setIcon(icon_edit)
layout.addWidget(edit_button)
cellWidget = QWidget()
cellWidget.setLayout(layout)
self.ui.course_table.setCellWidget(tablerow, 3, cellWidget)
while tablecol < numcols:
self.ui.course_table.setItem(tablerow, tablecol, PySide2.QtWidgets.QTableWidgetItem(str(row[tablecol])))
tablecol += 1
tablerow += 1
self.ui.course_table.horizontalHeader().setSectionResizeMode(0, QtWidgets.QHeaderView.Stretch)
self.ui.course_table.horizontalHeader().setSectionResizeMode(1, QtWidgets.QHeaderView.ResizeToContents)
self.ui.course_table.horizontalHeader().setSectionResizeMode(2, QtWidgets.QHeaderView.ResizeToContents)
The layout of this page of mine is as follows, (it basically has three frames who are in horizontal layout and the third frame contains the QTableWidget. The third frame's sizePolicy is set to Expanding so that it covers the whole main body while the two other performs are aligned to the top of the main body)
The .ui file (for only the course widget) is as follows
<widget class="QWidget" name="courses_page">
<layout class="QVBoxLayout" name="verticalLayout_12">
<item alignment="Qt::AlignLeft|Qt::AlignTop">
<widget class="QFrame" name="frame_13">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_12">
<item alignment="Qt::AlignLeft">
<widget class="QLabel" name="label_4">
<property name="font">
<font>
<family>Arial</family>
<pointsize>12</pointsize>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Courses Page</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item alignment="Qt::AlignTop">
<widget class="QFrame" name="frame_14">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_13">
<item alignment="Qt::AlignLeft">
<widget class="QFrame" name="frame_16">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_14">
<item>
<widget class="QPushButton" name="pushButton_2">
<property name="font">
<font>
<family>Calibri</family>
<pointsize>10</pointsize>
</font>
</property>
<property name="styleSheet">
<string notr="true">:hover
{
color: red;
font-size: 150%;
}</string>
</property>
<property name="text">
<string>Add New</string>
</property>
<property name="icon">
<iconset resource="icons.qrc">
<normaloff>:/icons/icons/icons8-add-48.png</normaloff>:/icons/icons/icons8-add-48.png</iconset>
</property>
<property name="iconSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton_3">
<property name="font">
<font>
<family>Calibri</family>
<pointsize>10</pointsize>
</font>
</property>
<property name="text">
<string>Delete All</string>
</property>
<property name="icon">
<iconset resource="icons.qrc">
<normaloff>:/icons/icons/icons8-remove-48.png</normaloff>:/icons/icons/icons8-remove-48.png</iconset>
</property>
<property name="iconSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item alignment="Qt::AlignLeft">
<widget class="QFrame" name="frame_17">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_15">
<item>
<widget class="QLineEdit" name="lineEdit">
<property name="font">
<font>
<family>Arial</family>
<pointsize>10</pointsize>
</font>
</property>
<property name="styleSheet">
<string notr="true">background-color: white;
border-bottom: 1px solid;
color: black;</string>
</property>
<property name="placeholderText">
<string>Search Course</string>
</property>
</widget>
</item>
<item alignment="Qt::AlignLeft">
<widget class="QPushButton" name="pushButton">
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="icons.qrc">
<normaloff>:/icons/icons/icons8-search-50.png</normaloff>:/icons/icons/icons8-search-50.png</iconset>
</property>
<property name="iconSize">
<size>
<width>24</width>
<height>24</height>
</size>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QFrame" name="frame_15">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_16">
<item>
<widget class="QTableWidget" name="course_table">
<property name="font">
<font>
<family>Arial</family>
<weight>50</weight>
<bold>false</bold>
<kerning>true</kerning>
</font>
</property>
<property name="styleSheet">
<string notr="true">:item
{
color: black;
}
QHeaderView:section
{
background-color: white;
font-weight: bold;
border: 0px;
}</string>
</property>
<property name="sizeAdjustPolicy">
<enum>QAbstractScrollArea::AdjustToContents</enum>
</property>
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<property name="alternatingRowColors">
<bool>true</bool>
</property>
<property name="gridStyle">
<enum>Qt::NoPen</enum>
</property>
<property name="sortingEnabled">
<bool>true</bool>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<attribute name="horizontalHeaderMinimumSectionSize">
<number>47</number>
</attribute>
<attribute name="horizontalHeaderHighlightSections">
<bool>true</bool>
</attribute>
<attribute name="horizontalHeaderStretchLastSection">
<bool>false</bool>
</attribute>
<attribute name="verticalHeaderVisible">
<bool>false</bool>
</attribute>
<attribute name="verticalHeaderCascadingSectionResizes">
<bool>false</bool>
</attribute>
<attribute name="verticalHeaderMinimumSectionSize">
<number>28</number>
</attribute>
<attribute name="verticalHeaderHighlightSections">
<bool>true</bool>
</attribute>
<attribute name="verticalHeaderShowSortIndicator" stdset="0">
<bool>true</bool>
</attribute>
<attribute name="verticalHeaderStretchLastSection">
<bool>false</bool>
</attribute>
<row>
<property name="text">
<string>1</string>
</property>
</row>
<row>
<property name="text">
<string>2</string>
</property>
</row>
<column>
<property name="text">
<string>Course Name</string>
</property>
</column>
<column>
<property name="text">
<string>Course Code</string>
</property>
</column>
<column>
<property name="text">
<string>Course Type</string>
</property>
</column>
<column>
<property name="text">
<string>Action</string>
</property>
</column>
<item row="0" column="0">
<property name="text">
<string>Ha</string>
</property>
</item>
<item row="0" column="1">
<property name="text">
<string>111</string>
</property>
</item>
<item row="0" column="2">
<property name="text">
<string>1</string>
</property>
</item>
<item row="0" column="3">
<property name="text">
<string>aaa</string>
</property>
</item>
<item row="1" column="0">
<property name="text">
<string>assa</string>
</property>
</item>
<item row="1" column="1">
<property name="text">
<string>Programming Fundamentals</string>
</property>
</item>
<item row="1" column="2">
<property name="text">
<string>55</string>
</property>
</item>
<item row="1" column="3">
<property name="text">
<string>55</string>
</property>
</item>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
The complete interface.ui code is given here: https://pastebin.com/bSEmRACT
(As an example, I have added two sample rows in the data)
The complete interface.py code is given here: https://pastebin.com/AA79ndcw
The code of main.py is also shared here: https://pastebin.com/EWNAmH6K

QPushButton doesn't do anything after clicking

I am a beginner with Qt and PySide with Python and I am facing a problem I don't know how to solve. I am working on FreeCAD and I try to design a simple window with push buttons but I can't make them work. When I click on them, their text should change but nothing happen.
Here is a piece of my code:
class ManageDialog:
def __init__(self, path):
self.form = FreeCADGui.PySideUic.loadUi(path)
self.form.setWindowTitle("Linked files manager")
QListWidgetItem("First item", self.form.listWidget)
QListWidgetItem("Second item", self.form.listWidget)
self.form.RemoveButton.clicked.connect(self.remove)
self.form.show()
def remove(self):
self.form.RemoveButton.setText("File removed")
path_to_ui = FreeCAD.getHomePath() + "/Mod/ThesisExistingBridges/ManageDialog.ui"
w = ManageDialog(path_to_ui)
My window is created according to a UI file done with Qt Creator. The design of the window is correct also and I can add items to a list widget for example but the buttons are not activated when clicked.
Here is a sample of UI file:
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Dialog</class>
<widget class="QDialog" name="Dialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>494</width>
<height>459</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<widget class="QListWidget" name="listWidget">
<property name="geometry">
<rect>
<x>10</x>
<y>10</y>
<width>471</width>
<height>401</height>
</rect>
</property>
</widget>
<widget class="QWidget" name="horizontalLayoutWidget">
<property name="geometry">
<rect>
<x>10</x>
<y>420</y>
<width>195</width>
<height>31</height>
</rect>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QPushButton" name="RemoveButton">
<property name="text">
<string>Remove</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="ReloadFromButton">
<property name="text">
<string>Reload from</string>
</property>
<property name="autoDefault">
<bool>false</bool>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QPushButton" name="OKButton">
<property name="geometry">
<rect>
<x>390</x>
<y>420</y>
<width>93</width>
<height>28</height>
</rect>
</property>
<property name="text">
<string>OK</string>
</property>
</widget>
</widget>
<resources/>
<connections/>
</ui>
I make it work in changing the method remove() in #static mode.
class ManageDialog:
def __init__(self, path):
self.form = FreeCADGui.PySideUic.loadUi(path)
self.form.setWindowTitle("Linked files manager")
QListWidgetItem("First item", self.form.listWidget)
QListWidgetItem("Second item", self.form.listWidget)
def clickedremove():
self.remove(self.form)
self.form.RemoveButton.clicked.connect(clickedremove)
self.form.show()
#staticmethod
def remove(f):
f.RemoveButton.setText("File removed")
path_to_ui = FreeCAD.getHomePath() + "/Mod/ThesisExistingBridges/ManageDialog.ui"
w = ManageDialog(path_to_ui)
It is maybe not the smartest way but it's working.

Automatically adjust the height of a `stackedWidget` page to the height of the widgets placed on it

I would like to adjust the height of the stackedWidget so that the height of the QTextEdit widget below it matches the height of the buttons on the active page of the stackedWidget. While the 4 QPushButton on page extended take up the entire space of the stackedWidget, the 2 QPushButton on page normal appear vertically in the middle and still have free space above and below.
But the 2 QPushButton on page normal should be at the top and the QTextEdit widget should be enlarged upwards. How can this be done?
main.py
import sys
from PyQt5.QtWidgets import QApplication, QMainWindow
from PyQt5.uic import loadUi
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
loadUi("mainwindow.ui", self)
def main():
app = QApplication(sys.argv)
main_window = MainWindow()
main_window.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
mainwindow.ui
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>601</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<property name="locale">
<locale language="English" country="UnitedKingdom"/>
</property>
<widget class="QWidget" name="centralwidget">
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<widget class="QStackedWidget" name="stackedWidget">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="normal" native="true">
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QPushButton" name="normal_start_button">
<property name="text">
<string>Start</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QPushButton" name="normal_stop_button">
<property name="text">
<string>Stop</string>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="extended">
<layout class="QGridLayout" name="gridLayout_3">
<item row="0" column="0">
<widget class="QPushButton" name="extended_quick_start_button">
<property name="text">
<string>Quick Start</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QPushButton" name="extended_stop_button">
<property name="text">
<string>Stop</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QPushButton" name="extended_slow_start_button">
<property name="text">
<string>Slow Start</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QPushButton" name="extended_pause_button">
<property name="text">
<string>Pause</string>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
<item row="1" column="0">
<widget class="QTextEdit" name="output"/>
</item>
</layout>
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>24</height>
</rect>
</property>
</widget>
<widget class="QStatusBar" name="statusbar"/>
</widget>
<resources/>
<connections/>
</ui>
Screenshot of page normal with only 2 QPushButton and unused space above and below:
Screenshot of page extended with 4 QPushButton and optimal use of the available space:
QStackedWidget takes as default height the default maximum height of the widget it contains, so in this case a possible solution is to set the height taking as reference the default height of the current widgets.
import sys
from PyQt5.QtWidgets import QApplication, QMainWindow
from PyQt5.uic import loadUi
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
loadUi("mainwindow.ui", self)
self.stackedWidget.currentChanged.connect(self.adjustHeight)
self.adjustHeight()
def adjustHeight(self):
h = self.stackedWidget.currentWidget().sizeHint().height()
self.stackedWidget.setFixedHeight(h)
def main():
app = QApplication(sys.argv)
main_window = MainWindow()
main_window.show()
def onTimeout():
sw = main_window.stackedWidget
sw.setCurrentIndex((sw.currentIndex() + 1) % sw.count())
# test
from PyQt5.QtCore import QTimer
timer = QTimer(timeout=onTimeout)
timer.start(1000)
sys.exit(app.exec_())
if __name__ == "__main__":
main()

dynamically populate comboBox Qt

I am trying to write a small app that compares xml. But right I am having a hard time doing the UI. I have a button that triggers a QFileDialog. I take the string input and populate a combobox. Unfortunately, the combobox stays empty. It seems to work when I hardcode it. But I am unable to get the app to do it dynamically. Is there something I am missing?
Here's the code:
import sys
from qtpy import QtCore, QtWidgets, uic
from qtpy.QtWidgets import QMainWindow, QApplication, QFileDialog
from qtpy.QtCore import QObject
class CompareSiteAndRepoWindow(QMainWindow):
def __init__(self):
super(CompareSiteAndRepoWindow,self).__init__()
uic.loadUi('CompareSiteAndRepo.ui',self)
self.BrowseLRPath.clicked.connect(self.browseFile)
self.buttonBox.rejected.connect(self.reject)
self.show()
def reject(self):
self.close()
def browseFile(self):
fileDiag = QFileDialog.getOpenFileName(self, 'Open file',
'c:\\',"xml/html (*.xml *.html)")
if(not fileDiag[0]):
print(fileDiag[0])
self.LRPathComboBox.addItem(fileDiag[0],0)
if __name__ == '__main__':
app = QApplication(sys.argv)
window = CompareSiteAndRepoWindow()
sys.exit(app.exec())
the CompareSiteAndRepo.ui file
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>CompareLabToSiteDLG</class>
<widget class="QMainWindow" name="CompareLabToSiteDLG">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>316</width>
<height>262</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralwidget">
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="LRLabel">
<property name="text">
<string>Load Report</string>
</property>
</widget>
</item>
<item>
<widget class="QSplitter" name="splitter">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<widget class="QComboBox" name="LRPathComboBox"/>
<widget class="QPushButton" name="BrowseLRPath">
<property name="text">
<string>Browse</string>
</property>
</widget>
</widget>
</item>
<item>
<widget class="QLabel" name="LP2Label">
<property name="text">
<string>LaunchPadData repo layout</string>
</property>
</widget>
</item>
<item>
<widget class="QSplitter" name="splitter_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<widget class="QComboBox" name="LP2RepoPath"/>
<widget class="QPushButton" name="BrowseLP2RepoPath">
<property name="text">
<string>Browse</string>
</property>
</widget>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>316</width>
<height>26</height>
</rect>
</property>
</widget>
<widget class="QStatusBar" name="statusbar"/>
</widget>
<resources/>
<connections/>
</ui>
the problem is the statement if (not fileDiag[0]):, fileDialog[0] is a text that if we evaluate it as boolean will return True for any text except it is empty and if you deny it will be False if the text is not empty or True if it is, which is contrary to what you want:
fileDiag[0] not fileDiag[0]
+--------------+--------------+
"" True
"some text" False
One solution is to suppress the not:
if fileDiag[0]:
[...]
But another solution is to compare if the text is not empty as I show below:
def browseFile(self):
filename, _ = QFileDialog.getOpenFileName(self, 'Open file', 'c:\\',"xml/html (*.xml *.html)")
if filename != "":
self.LRPathComboBox.addItem(filename, 0)

Categories

Resources