How to prevent no selection in QTableWidget? - python-3.x

I have a QTableWidget with some rows in it. I want selection to be always present. But once I click somewhere on the Table outside the rows I lose my selection. Could someone help me with this problem?

The simplest solution is to ensure that an item exists at the coordinates the user clicks in.
This can be done by ensuring that QTableWidget.indexAt(pos) returns a valid index: if it is, it means that an item exists there, so we can proceed with the base class mousePressEvent, otherwise we just ignore it.
class AlwaysSelectedTable(QtWidgets.QTableWidget):
def mousePressEvent(self, event):
if self.indexAt(event.pos()).isValid():
QtWidgets.QTableWidget.mousePressEvent(self, event)

Related

How to get the widget that is focused in when I focus out of another one? (in order to force focus avec a <FocusOut> bind)

I have a table made of multiple entries in tkinter. When I change one entry I want to update all others. I have achieved this by binding all entries with a <FocusOut> function that refreshes the table. This works fines as long as I do not focus from one entry to another.
What works: I click on one entry, I type what I want, I click somewhere else in the window (except another entry) and everything updates fine. I can continue on.
What doesn't: I click on one entry, I type what I want and I click on another entry. This updates the table, but I can not type anything nor click on any other entry as long as I do not click first on a 'non entry' part of the frame. As if the <FocusOut> bound prevented me from focusing in to the next one.
I would like to either:
keep track of the next entry I click on in order to focus_force() it after the refresh has run.
or solve this problem with any other welcome suggestion.
Here is a simplified version of my code:
entries = {}
def table_refresh():
for y, name in zip(list_y, list_names):
insertion = "some value that is function of the other entries"
entries[name] = tk.Entry(master)
entries[name].place(x=x, y=y)
entries[name].insert(0, insertion)
entries[name].configure(**entry_params)
entries[name].bind("<FocusOut>", on_focusout)
def on_focusout(event):
table_refresh()

OpenEdge: Get clicked column in a browser

I have a browser object and I'm trying to get the number of the column in which the user clicked a cell - is that possible? My browser is called brw-misc so when I try:
brw-misc:CURRENT-COLUMN
I get '?' in return unless I've clicked on the column heading to sort the records before that.
brw-misc:COLUMN
Always returns '1'.
The CURRENT-COLUMN attribute only works with editable browsers. That's probably why you're getting a null (?). The COLUMN attribute is where the browser is positioned on the frame.
If the browser is editable, you can use
brw-misc:CURRENT-COLUMN:LABEL
to get the column label. You can then use that to figure out which column number that is.
TheDrooper offered some good advice above.
If that column is editable, and clicking it actually gets inside the field (to update the value), then you can query FOCUS:NAME to learn what is the column name you just clicked. It's a handle, all handle attributes apply.
It's going to be way trickier if you don't have the fields enabled, though. You didn't specify if this is client GUI, I'll go ahead and assume it is (rather than Webspeed). You need to capture mouse coordinates using Windows DLLs, your window coordinates (using X and Y attributes), then your browse columns X and Y, and hope that browse is not horizontally scrollable, lol.
If you do all that, you can tell which column they clicked on. Oh, and since (As far as I understood) you're more worried on which column he clicked on, rather than which cell, you're going to value X over Y (but don't forget to test to make sure they actually clicked INSIDE the browse at all).
Off the top of my mind, that's what I can think of. Not sure if it helps, but it might point you somewhere!

Issue rendering the selected cell on a QTableView

I have a custom QTableView and a custom QAbstractTableModel. The view only allows single selections. I'm trying to customize the background color of the selected cell under some conditions with no success. I expected to do it by combining the data method of the model with the selectionChanged method of the view. For instance, let's suppose I want to change the color of the selected cell when it matches a given row. My code for the selectionChanged method is:
def selectionChanged(self, selected, deselected):
#QtGui.QTableView.selectionChanged(self, selected, deselected)
# Get the selected indexes from the QItemSelection object
selection = selected.indexes()
# Let the model track the selected cell
self.tmodel.selected_index = selection[0]
# Desperately try to make it work
self.tmodel.dataChanged.emit(selection[0], selection[0])
self.viewport().update()
My simplified code for the data method is:
def data(self, index, role=QtCore.Qt.DisplayRole):
if not index.isValid():
return None
# Some code here dealing with several roles
if role == QtCore.Qt.DisplayRole:
...
elif role == QtCore.Qt.BackgroundRole:
if ((index == self.selected_index) and (index.row() == 3)):
print '++++ displaying selected'
return QtGui.QColor(QtCore.Qt.yellow)
else:
return QtGui.QColor(QtCore.Qt.green)
else:
return None
The non selected cells have a green background as expected. The strange thing is that when I select a cell in the matching row, the message ++++ displaying selected is printed but the selected cell has the system default background instead of a yellow one. I must be missing something important/obvious here but I've no idea about what it is.
Update
I know I can achieve my goal using a custom delegate and implementing its paint method but I'd like to know why the code above fails.
OK, I think I got it. The think is that the default delegate uses the values returned by data in order to render the table cells. Accordingly to the docs:
By supplying appropriate item data for each role, models can provide
hints to views and delegates about how items should be presented to
the user. Different kinds of views have the freedom to interpret or
ignore this information as required.
So the behavior described in the question is explained as follow: non selected cells are rendered in the standard way by the default delegate which implies the color returned by data method will be used. However, selected cell are rendered in a different way by the default delegate, the value returned by data method is ignored in this case because it uses the background provided by the system style.

Modify Key press action in QTableView (PyQt4)

I'm using the QTableView class to display a table from a database. I want to allow the user to edit the table using the keyboard only.
However, the default behavior of the class is to reset the focus to the starting index of the table after 2 edits, ie. I edit a cell, press the "Down" key, edit the cell, again press the "Down" key, at which point the table loses focus; next time I press the down key, the first cell of the table gains focus.
What methods of the class should I look at to modify this behavior?
I'm using the single item selection mode:
self.entryView = QTableView()
self.entryView.setModel(self.logModel)
self.entryView.setItemDelegate(LogDelegate(self))
self.entryView.setSelectionMode(QTableView.SingleSelection)
self.entryView.setSelectionBehavior(QTableView.SelectItems)
I used TreeWidget before so they should be similar. How about explicitly specifying the "active item" by calling setCurrentItem() method after modification? in this way you can always have the correct focus

CListCtrl - how to find it is selected

I have got a CDialog Class, inside which there are two ClistCtrl classes.
I want to find out which of the listCtrl's is selected at the moment.
say, listCtrl A and B. Even when I move between A and B, suppose first I go to A and select a row. Then even when I go to B and select an item there, item in A remains selected as I don't come to know that I have gone in other list.
Any suggestions, how I can find this.
If understand you correctly, you need to know which one of list boxes has a focus. You could do that by calling GetFocus(), it returns a pointer to the focused control.
The problem you might have though is when your dialog is not an active window and then focus would be somewhere else. In this case you should be tracking WM_SETFOCUS and WM_KILLFOCUS messages and keeping record of which of the list boxes was activated last. In MFC there are callbacks CWnd::OnSetFocus and CWnd::OnKillFocus that could be used to achieve that.
I found a way of doing this. I can register for NM_Click notifications on both the lists
When list A is selected, I set curSel of list B to -1 and vice versa.

Resources