Results 1 to 10 of 10

Thread: PyQt5 - QTableView

  1. #1
    Join Date
    Feb 2021
    Posts
    5
    Thanks
    1
    Qt products
    Qt5
    Platforms
    Windows

    Default PyQt5 - QTableView

    I have a ui designed in Qt that uses the QCalendarWidget, QTableView, and in the Python code uses QtSql.

    Upon startup, I query a SQL database for a whole date range of the designed timeframe, and populate the QTabelView with that result.

    I am able to select the records and return the value to through the signal/slot to the Python code and able to use the values within the code.

    If a user selects a specific date, the code requeries SQL for that specific date and repopulates the QTableView. All that works fine.

    The problem is that after any re-query, the QTableView signal/slot does not update if a user selects a value.

  2. #2
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,240
    Thanks
    303
    Thanked 865 Times in 852 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: PyQt5 - QTableView

    the QTableView signal/slot does not update if a user selects a value
    And what do you mean by that? What signal, what slot? Selection in table views is usually notified by a QItemSelectionModel, not the table view.
    <=== The Great Pumpkin says ===>
    Please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.

  3. #3
    Join Date
    Feb 2021
    Posts
    5
    Thanks
    1
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: PyQt5 - QTableView

    Quote Originally Posted by d_stranz View Post
    And what do you mean by that? What signal, what slot? Selection in table views is usually notified by a QItemSelectionModel, not the table view.

    In my python code, I do an initial SQL query and populate the QTabelView with the results.

    At this point in time, a user can click on a record, and the value is returned to the Python code via:
    self.TableViewList.selectionModel().selectionChang ed.connect(self.get_Details)

    And the user can click on any record and it will connect and the get_Details will execute (only displays what was chosen by the user at this point).

    Now, one of the features I've already developed, was that if the user selects a date via the QCalendarWidget and the subsequent python code:
    self.Calendar.selectionChanged.connect(self.requer y)

    In the code it will requery SQL with the selected date, and will populate the QTableView with the correct dataset.

    BUT ... if the user were to click on a record, the connection back to the Python code does not trigger.

  4. #4
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,240
    Thanks
    303
    Thanked 865 Times in 852 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: PyQt5 - QTableView

    BUT ... if the user were to click on a record, the connection back to the Python code does not trigger.
    What connection back to the Python code? If you have set up a slot to handle the selection model's selectionChanged() signal, then that slot should be called. If the user is just clicking on an item or moving using the up / down arrow keys, then the currentChanged() signal is emitted. Maybe this is what you are looking for.
    <=== The Great Pumpkin says ===>
    Please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.

  5. #5
    Join Date
    Feb 2021
    Posts
    5
    Thanks
    1
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: PyQt5 - QTableView

    As I indicated above, for the QCalendarWidget uses the code:

    self.Calendar.selectionChanged.connect(self.requer y)

    and this code works fine. I can scroll through and select a date and it works every time.
    Now with the QTableView, I use the code

    self.TableViewList.selectionModel().selectionChang ed.connect(self.get_Details)

    This works with the original population of the QTableView, but once I repopulate with the new data from the requery due to the date change, it ceases to function, the selectionChanged.connect just doesn't trigger the get_Details any longer.

  6. #6
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,240
    Thanks
    303
    Thanked 865 Times in 852 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: PyQt5 - QTableView

    the selectionChanged.connect just doesn't trigger the get_Details any longer.
    I don't think you understand how signals and slots work. A connection (via connect()) between a signal (selectionChanged()) amd a slot (get_Details()) does not result in an immediate function call to the slot code.

    What a connect() means is this: "In the future, when this signal is emitted by the signalling object instance (selectionModel), call this slot (get_Details()) and pass that slot the arguments provided by the signal". (Which in this case are the QModelIndex indexes that have been selected and deselected).

    You do not call connect() every time you want to retrieve the new selection and pass that to the slot. You generally call connect() once when you are creating the object instances you are connecting. Thereafter, you simply wait for your slot to be called whenever the signalling object changes state.

    You haven't posted enough of your code to verify what you are actually doing, but your description of how you are invoking connect() makes it seem like you have a misunderstanding of the protocol.
    <=== The Great Pumpkin says ===>
    Please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.

  7. #7
    Join Date
    Feb 2021
    Posts
    5
    Thanks
    1
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: PyQt5 - QTableView

    The bulk of the code is as follows. I have not included the SQL connection string as this works.

    Qt Code:
    1. import sys
    2. import datetime
    3. from PyQt5 import QtWidgets as qtw
    4. from PyQt5 import QtCore as qtc
    5. from PyQt5 import QtGui as qtg
    6. from PyQt5 import QtSql as qts
    7. from PyQt5 import uic
    8. from PyQt5.QtSql import QSqlDatabase
    9.  
    10. MainWindow_Ui, MainWindow_Base = uic.loadUiType('CriticalAlarmListGUI.ui')
    11.  
    12.  
    13.  
    14. #class MainWindow(qtw.QMainWindow, Ui_MainWindow):
    15. class MainWindow(MainWindow_Base, MainWindow_Ui):
    16. events = {}
    17.  
    18. def __init__(self):
    19. """MainWindow constructor.
    20.  
    21. This widget will be the main window.
    22. Define all the UI components in here.
    23. """
    24. super().__init__()
    25. # Main UI code goes here
    26. self.setupUi(self)
    27.  
    28. # Connect to databases
    29. #removed for security purposes
    30.  
    31.  
    32. # Build the Query
    33. StartDate = datetime.date(2020, 11, 1)
    34. EndDate = datetime.date.today()
    35.  
    36. # Set the valid date range for the Calendar
    37. self.Calendar.setDateRange(StartDate, EndDate)
    38.  
    39. # Format Dates for SQL
    40. StartDate = "'" + str(StartDate.strftime("%m/%d/%Y")) + "'"
    41. EndDate = "'" + str(EndDate.strftime("%m/%d/%Y")) + "'"
    42.  
    43. # Get the list of critical alarms within the date range
    44. CriticalAlarms = self.get_Critical_Alarms(StartDate, EndDate)
    45.  
    46. # Loop through the Critical Alarm list and update the calendar date format of the results
    47. for i in range(CriticalAlarms.rowCount()):
    48. datetime_str = CriticalAlarms.record(i).value("EventStamp")
    49. datetime_obj = datetime.datetime.strptime(datetime_str, '%Y-%m-%d %H:%M:%S.%f0')
    50.  
    51. # Update the format of the date on the calendar day that the alarm occured
    52. format = qtg.QTextCharFormat()
    53. format.setFont(qtg.QFont('Times', 15))
    54. date = qtc.QDate(datetime_obj)
    55. self.Calendar.setDateTextFormat(date, format)
    56.  
    57. # Single Date Selected on the Calendar
    58. self.Calendar.selectionChanged.connect(self.config_Critical_Alarms)
    59.  
    60. # Single record selected on the CriticalAlarmList widget
    61. self.CriticalAlarmList.selectionModel().selectionChanged.connect(self.get_Critical_Alarm_Details)
    62.  
    63. # End main UI code
    64. self.show()
    65.  
    66.  
    67. def config_Critical_Alarms(self):
    68. print ("config_Critical_Alarms")
    69. CriticalAlarms = None
    70. StartDate = self.Calendar.selectedDate()
    71. EndDate = StartDate.addDays(1)
    72.  
    73. StartDate = "'" + qtc.QDate.toString(StartDate, 'MM/dd/yyyy') + "'"
    74. EndDate = "'" + qtc.QDate.toString(EndDate, 'MM/dd/yyyy') + "'"
    75. CriticalAlarms = self.get_Critical_Alarms(StartDate, EndDate)
    76.  
    77.  
    78. def get_Critical_Alarms(self, StartDate, EndDate):
    79. print ("get_Critical_Alarms")
    80.  
    81. alarm_state = "'UNACK_ALM'"
    82. queryString = f'SELECT EventStamp, TagName, Description, Priority FROM v_AlarmHistory WHERE (AlarmState = {alarm_state}) '\
    83. f'AND (EventStamp >= {StartDate}) AND (Priority <= 10) AND '\
    84. f'(EventStamp <= {EndDate}) ORDER BY EventStamp DESC'
    85.  
    86. # Process the SQL Query
    87. CriticalAlarms = qts.QSqlQueryModel()
    88. CriticalAlarms.setQuery(queryString)
    89.  
    90. self.CriticalAlarmList.setModel(CriticalAlarms)
    91. self.CriticalAlarmList.resizeColumnsToContents()
    92. self.StatusLabel.setText('Found {0} critical alarms between {1} and {2}'.format(CriticalAlarms.rowCount(), StartDate, EndDate))
    93.  
    94. return(CriticalAlarms)
    95.  
    96.  
    97. def get_Critical_Alarm_Details(self, selected):
    98. print ("get_Critical_Alarm_Details")
    99. indexes = self.CriticalAlarmList.selectionModel().selectedRows()
    100. model = self.CriticalAlarmList.model()
    101. for index in indexes:
    102. self.StatusLabel.setText('Selected row: {0}, Tag: {1}'.format(index.row(), model.data(model.index(index.row(), 1))))
    103.  
    104.  
    105. def UiComponents(self, datetime_obj):
    106. print ("UiComponents")
    107. # Calendar day format
    108. format = qtg.QTextCharFormat()
    109. format.setFont(qtg.QFont('Times', 15))
    110. date = qtc.QDate(datetime_obj)
    111. value = self.Calendar.dateTextFormat()
    112. self.label.setWordWrap(True)
    113. self.label.setText("Date: " + str(value))
    114.  
    115.  
    116.  
    117.  
    118. # Main
    119. if __name__ == '__main__':
    120. app = qtw.QApplication(sys.argv)
    121. # Requirement to save a reference to MainWindow
    122. # if it goes out of scope, it will be destroyed.
    123. mw = MainWindow()
    124. sys.exit(app.exec())
    To copy to clipboard, switch view to plain text mode 




    I believe I have the signals and slots set up correctly. Please make any suggestions to why I do not get the continued function of the signal.
    Last edited by d_stranz; 27th February 2021 at 19:21. Reason: missing [code] tags

  8. #8
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,240
    Thanks
    303
    Thanked 865 Times in 852 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: PyQt5 - QTableView

    OK, I am not a Python expert, but what I think is happening is that in get_Critical_Alarms() you are setting a new model on your list. This causes the selectionModel() to become invalid, and therefore the selectionChanged() signal is disconnected.

    Try adding the connect() statement after line 90.
    <=== The Great Pumpkin says ===>
    Please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.

  9. The following user says thank you to d_stranz for this useful post:

    szotke (27th February 2021)

  10. #9
    Join Date
    Feb 2021
    Posts
    5
    Thanks
    1
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: PyQt5 - QTableView

    Quote Originally Posted by d_stranz View Post
    Try adding the connect() statement after line 90.

    That worked.

    Thank you very much.

  11. #10
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,240
    Thanks
    303
    Thanked 865 Times in 852 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: PyQt5 - QTableView

    Sure. I think your original idea would work if you did not create a new CriticalAlarms model every time you make a query. If you make CriticalAlarms a member variable of your class, create it and connect to the selectionChanged() signal and then simply call setQuery() on that instance each time the calendar selection changes, your model will be reset with each query and the current selection will be cleared. The selection model won't be destroyed, it will just be cleared. The next time an item is selected, the selectionChanged() signal will be emitted.

    So basically, remove line 87 above, remove the new connection you added after line 90 (keeping the original one from line 61), and make CriticalAlarms into self.CriticalAlarms. Then I think your original code will work. You probably don't have to change get_CriticalAlarms() return value since you'll be returning the same object reference (self.CriticalAlarms).
    <=== The Great Pumpkin says ===>
    Please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.

Similar Threads

  1. Bug in Qt5.12 or PyQt5.11.3???
    By barkowski@shinobi-mail.de in forum Qt Programming
    Replies: 5
    Last Post: 27th January 2019, 10:21
  2. PyQt5 Questions
    By Miton in forum Newbie
    Replies: 6
    Last Post: 30th January 2017, 12:10
  3. align column of QTableView in pyqt5
    By nlgootee in forum Qt Programming
    Replies: 5
    Last Post: 6th July 2016, 18:03
  4. How can I install pyQt5
    By prachi kamble in forum Installation and Deployment
    Replies: 0
    Last Post: 4th June 2015, 12:13
  5. PyQt5 QPixmap
    By ChrisOfBristol in forum Newbie
    Replies: 4
    Last Post: 4th April 2015, 21:48

Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.