Direction needed (tables)



  • I will try to be as brief as possible. I am quite new to Qt but not to programming.

    I need to make an editable table with selectable, insertable and movable rows and selectable columns. The table is small and will show all data at all times. It's pretty much just three columns i.e. three values per row (x,y,z) and these values are what the user will be adding and editing. The number of rows will be small too - not more than half a dozen or so per table.
    Also, the cells should be sensitive to key events - enter, tab, escape and some other - and these are what I would need to specify as well.

    Naively, I jumped on QTableWidget because that is what I saw first and assumed that was my solution, defined the required classes and event filters but, of course, it didn't work since QTableWidgetItem does not accept installEventFilter. Maybe that wouldn't have been my only problem but was the spot on the wall that I hit first.
    Now I started reading the whole Model/View programming thing, but I am not sure if that is what I really need as it seems like a lot of work for a relatively small and simple problem that I am trying to solve.

    I want to add that the key events I have in mind are not just for navigating around the table but also for signaling when the entered numbers should be verified and/or synced with the actual data. This is pushing me towards the whole Model/View system but, again, to my Qt-untrained eyes my problem seems too small and simple for all that. The code I wrote was short and simple, just an event filter which was then installed on every cell - but it can't work so the point is moot I guess.

    My question: From what I explained above, what should I be looking at? Keep reading on how to use QAbstractTableModel or QTableView, somehow fix my first idea or something entirely different?

    Thanks in advance.



  • Hi,

    I don't have much experience with QTableWidget but it looks like it offers everything you need. You have all the features of QTableView and more. Look at the signals QTableWidget and its super classes provide.

    If that's not enough, you can derive your class from QTableWidget and get access to all of those protected functions which must be more than enough.

    I am pretty sure you can do what you want without installing any filters. If you not familiar with signals and slots, I suggest that you check QObject and the core technologies around it.


  • Lifetime Qt Champion

    Hi and welcome to devnet,

    What are you trying to filter exactly ?

    One more element to take a look at is the QStyleItemDelegate, it should help you understand how input is handled



  • ckakman, thank you for your response. Problem with QTableWidget is that its cells are QTableWidgetItem which is not a QObject. That is why my attempt to derive my table from QTableWidget didn't work - it couldn't receive key events from its cells. Later I read that QTableWidget was not meant to be a base class anyway, for whatever reason.



  • Hello SGaist,

    The idea is to have a table that does not require any mouse action or pressing a separate button to add, edit, verify or sync the entries with the actual data, add a new row at the end of the table, or navigate the table. Everything should be doable by key presses while working in the table and the action triggered by these presses (verify the data, sync the data, go to next cell, add a row etc) would also depend on whether the active cell contains new data or the existing data is being edited.

    From my understanding, which apparently might be completely wrong, for this to work I need some kind of key event filters installed on every table cell.

    edit. To explain my first attempt - my table was derived from QTableWidget and it had an event filter which collected all necessary key presses on table cells and told the underlying system what to do in each case. This event filter was installed on every cell but that couldn't work as cells are QTableWidgetItem.

    [quote author="SGaist" date="1421451930"]Hi and welcome to devnet,

    What are you trying to filter exactly ?

    One more element to take a look at is the QStyleItemDelegate, it should help you understand how input is handled [/quote]



  • The cells in QTableWidget are by default editable. QTableWidget's signals notify you about changed items.

    Check out the protected functions of QTableWidget. There are functions which allow you get an item from QModelIndex and vice verse. Also check out the signals of QAbstractItemView, grandparent of QTableWidget, which provide lower-level notifications about the cells. Those protected functions allow you get the item if you are using QAbtractItemView's signals. Hence QTableWidget is expected to be inherited from if you need to.

    By the way, even if you used a QTableView with a custom model, you wouldn't have a cell represented as a QObject-based object. Notifications about data in these widgets are sent from the view or a widget derived from that view.



  • ckakman,

    That is what I have been doing - reading on abstract models and tables - but it seemed like overkill for something so small and simple as my table is (or at least it seems simple) so I decided to ask first.



  • Have you checked how QTableWidget behaves by default? It allows navigation with arrow keys or the tab key, editing a cell, multi-cell selection with Shift or Ctrl, saving the entered data with Enter, ending editing without saving data to cell with Escape. It is already there.

    You just need to connect to a couple of signals if you get notified when the user edits a cell.

    Apparently I am not seeing what functionality is missing in QTableWidget that you need.



  • If your Qt and Qt Creator installed, it would take < 1 minute to start playing with QTableWidget:

    • Create a Widget project.
    • Double click the ui file to open it in Design mode.
    • Drop a table widget.
    • Edit the row and column count in the Property viewer.
    • Click Run.


  • The fact that QTableWidget provides many things I need for my table - selectable, movable, insertable rows, navigation by Tab press and many others - is why I chose it for the base class. The only thing I had to do is specify additional key presses and system reactions to them, which was a simple and quick work but it didn't work.

    I apologize if I am not being clear enough, that is probably due to me being new to Qt.
    To reiterate, my problem is that my table has to know these things:

    • position of the active cell

    • if the active cell received a key press, and which key press (enter, tab, escape...)

    and I couldn't do it using event filters. What I am trying to figure out is another way to achieve this in the most simple and natural way.

    Thanks for your patience.



  • [quote author="applefier" date="1421485441"]

    The idea is to have a table that does not require any mouse action or pressing a separate button to add, edit, verify or sync the entries with the actual data, add a new row at the end of the table, or navigate the table. Everything should be doable by key presses while working in the table and the action triggered by these presses (verify the data, sync the data, go to next cell, add a row etc) would also depend on whether the active cell contains new data or the existing data is being edited.
    [/quote]

    All of these can be done with QTableWidget without deriving from it and without using any of the base classes' members and signals.

    I have already mentioned the default navigation and editing capabilities of QTableWidget. You can validate data in a slot connected to itemChanged(). You can programmatically start editing a cell with editItem(), change the row/column count setRow/ColumnCount(), etc.



  • If default navigation features are not enough, you can combine these two:
    @
    void QWidget::​keyPressEvent(QKeyEvent * event)
    QList<QTableWidgetItem *> QTableWidget::​selectedItems() const
    @



  • [quote author="ckakman" date="1421488880"]If default navigation features are not enough, you can combine these two:
    @
    void QWidget::​keyPressEvent(QKeyEvent * event)
    QList<QTableWidgetItem *> QTableWidget::​selectedItems() const
    @[/quote]

    I forgot to say this: keyPressedEvent() is a protected function hence requires a QWidget subclass to reimplement it. If you just want to receive the keyPressedEvent() for the table, and not a parent of it, then you need to derive from QTableWidget.



  • Thanks ckakman, if what you say is true - that I can do everything I need using QTableWidget - that is great. I will go check out its documentation again.



  • [quote author="applefier" date="1421490324"]Thanks ckakman, if what you say is true - that I can do everything I need using QTableWidget - that is great. I will go check out its documentation again.[/quote]

    :) Don't take my word for it but I am pretty sure what I'm saying is true.


  • Lifetime Qt Champion

    Yep, ckakman is right.

    One thing you have to keep in mind if your derive from QTableWidget is to not forget to call the base class implementations of the methods you reimplement otherwise you'll loose some of the functionalities provided



  • Thanks SGaist,

    hearing good news from one source was great, hearing it from two is fantastic. Thanks for the reminder too, I will keep that in mind.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.