Argh, I hit a really weird problem.
I have a breakpoint set, and I'm trying to inspect a BOOL value. The summary in the locals section says clearly that it is NO. However, I'm pretty sure that the paramater passed in should have evaluated to YES.
So, I hovered my mouse over the variable in question and get the following screen, where the value is 0x01, and the summary says it is NO. (screen attached for your amusement).
What is going on here?
I have reported this bug to Apple and this is the work-around (solution) that works by me:
Right click on the variable in the Variables View and select "Edit
Summary Format…". Do you see the string "NO" in there? If so, delete
that.
Related
Environment: Version 11.0 beta 3 (11M362v)
Here's the full text:
invalid mode 'kCFRunLoopCommonModes' provided to CFRunLoopRunSpecific - break on _CFRunLoopError_RunCalledWithInvalidMode to debug.
This message will only appear once per execution.
Hello World
This message only appears when I click on a UISwitch button that is connected to an action; here, printing "Hello World".
Apparently the behavior of the action isn't affected.
As a comparison, I've created a UIBarButtonItem in the toolbar which behaves normally. So there's something fishy about the switch button.
Question: why would this appear and what does it mean? Remedy?
I think it's a warning that Apple should fix it itself. Even in this sample project which is from WWDC19 this problem exists. There is a UISwitch in a cell of a table. When I tap it, the mentioned warning is raised.
So, in my view, it is a bug that Apple should deal with.
Judging from the replies by Apple Developer Relations to this post, this is a bug in UIKit and one that Apple is tracking. Until the bug is fixed, the advice is to treat this as "log noise".
I had a similar problem:
When I got the call-back from the UISwitch, I reloaded the UITableView.
I think that the call-back is initiated before the UISwitch finishes changing its context, and reloading the cell in that state creates some conflict.
With that theory, I solved my problem like so:
I separated the cells into sections, where the cell with the UISwitch was in its own section.
When I got the call-back from the UISwitch, I reloaded all the sections except the section that has the cell with the UISwitch.
UPDATE3 - SOLVED with reservations, please see my solution below; leaving it open since the cause of the problem is unclear, and I don't know how robust the solution is.
UPDATE1: here's the short short version.
Currently, after .setEditText on a QComboBox, I get this:
so the next thing you type will overwrite 'Team '.
But the desired effect is this (unhighlighted / unselected), so that the next thing you type will be appended to 'Team ' instead of overwriting it:
Thanks for any help. The rambling details are below, which is the original post:
(this is all PyQt 5.4)
UPDATE2:
Apparently python doesn't think anything is actually selected:
self.entryForm.ui.teamField.lineEdit().setText("Team ")
print("selected text:"+self.entryForm.ui.teamField.lineEdit().selectedText())
prints "selected text:" and nothing else. To make sure that's working:
self.entryForm.ui.teamField.lineEdit().setText("Team ")
self.entryForm.ui.teamField.lineEdit().setSelection(0,4)
print("selected text:"+self.entryForm.ui.teamField.lineEdit().selectedText())
prints "selected text:Team"
So that might be why many of the methods that affect selection are not working as expected (.deselect(), .setSelection(5,5), etc, and even some of the other methods give unexpected behavior, i.e. cursorForward(False,1) or cursorBackward(False,1) and such.
Original post:
This is for a radio log GUI, so keyboard interactions must be minimal and intuitive. openNewEntryForm (below) is called as a slot from a pushbutton on the main application GUI window:
self.ui.pushButton.clicked.connect(self.openNewEntryDialog)
It can also be called using a keyPressEvent in the same class:
def keyPressEvent(self,event):
if type(event)==QKeyEvent:
print("QKeyEvent:"+str(event.key()))
if event.key()==Qt.Key_T:
self.openNewEntryDialog('t')
event.accept()
else:
event.ignore()
Here's the method in question:
def openNewEntryDialog(self,key=None):
self.entryDialog=newEntryDialog()
if key=='t':
self.entryDialog.ui.to_fromField.setCurrentIndex(1)
self.entryDialog.ui.teamField.setFocus()
self.entryDialog.ui.teamField.setEditText("Team ")
if self.entryDialog.exec_():
self.newEntry(self.entryDialog.getValues()) # adds the log entry
so, the intended key press sequence is (from the main application GUI window):
a single keyboard press of 't' will open the entryForm, set the to_fromField to index 1 (which happens to be "TO"), give focus to teamField (also a QComboBox), set its text to "Team " and set itself up so that the very next keypress will appear as the text following "Team " in teamField.
So, starting from the main app GUI again, the plan is that typing 't3' should open the new entry window, set the to_fromField to "TO", and set the teamField to "Team 3", ready for a keypress of the tab key to move on to the next field in the entryForm.
The problem is that the teamField.setEditText("Team ") call leaves all of the text highlighted/selected, so that a subsequent key press of '3' would replace "Team " with "3"; I'm looking for a way to unhighlight/unselect "Team " but leave the cursor active at the right of that string, so that the subsequent key press of '3' would make the entire string "Team 3".
Ideas? Thanks in advance.
You can access the line-edit of the combo box, and then remove the selection:
self.entryDialog.ui.teamField.setEditText("Team ")
self.entryDialog.ui.teamField.lineEdit().deselect()
UPDATE:
The above code is correct, but it seems that the dialog will then clobber it when it initialises the focus handling for its child widgets after it is shown. If a dialog is opened with exec(), it will start its own event-loop, and some events (including focus events) will only be processed after it is fully shown. This is why it may appear that some changes made to child widgets before the dialog is shown are being ignored.
One way to work around this is to use a single-shot timer to ensure the changes are only attempted after the dialog is shown.
So add a method to the entry dialog class something like this:
def resetUI(self, key):
if key == 't':
self.ui.to_fromField.setCurrentIndex(1)
self.ui.teamField.setFocus()
self.ui.teamField.setEditText('Team ')
QtCore.QTimer.singleShot(0, self.ui.teamField.lineEdit().deselect)
and then use it like this:
def openNewEntryDialog(self, key=None):
self.entryDialog = newEntryDialog()
self.entryDialog.resetUI(key)
if self.entryDialog.exec_():
self.newEntry(self.entryDialog.getValues())
SOLVED with reservations, see UPDATE3 in the original post.
So, with the initial text all highlighted, tests show that it didn't actually think anything was selected. This solution was just stumbled upon by trial and error, fiddling with setting and clearing focus, selecting text and trying deselect:
def openNewEntryDialog(self,key=None):
self.entryForm=newEntryDialog()
if key=='t':
self.entryForm.ui.to_fromField.setCurrentIndex(1)
self.entryForm.ui.teamField.lineEdit().setFocus()
self.entryForm.ui.teamField.lineEdit().setText("Team ")
self.entryForm.ui.teamField.lineEdit().setSelection(5,1)
Notice there are two spaces after 'Team' and the second one is intentionally selected. Then the very next keypress will overwrite that second space; that is basically the desired behavior.
Anyway it looks like something bizarro with the selection scheme; one way to look at this is that the highlight isn't really a selection, but, if you set a valid real selection then it will override the original highlighted 'pseudo-selection'. The original highlighting behaves like a selection in that a keypress will replace everything that's highlighted, but, not like a selection in that the selection methods reveal that there is no 'selection', see UPDATE2 in the original post.
Can anyone help explain this behavior? I'd like to build some more confidence in it before accepting this coincidental answer.
Thanks
newbie question: can anyone tip me to how to understand/interpret what is displayed in the debugger var pane?
Ex: I am passing an NSDictionary as a method param. I set a breakpoint so I can examine the values in the dictionary. The image below (if it comes through..) shows the expanded view of this var in the debugger. It correctly reports that it contains 3 name/value pairs but as I expand all the sections, I simply can not find where these are stored.
Do I have to create local vars of these name/value pairs in order to view them when I want to check? I know I can use NSLog or printf but sometimes I just want a quick peek.
Right click the variable, click "Edit Summary Format" and type the following:
{(NSString*)[$VAR description]}:s
This replaces the GDB formatter for NSDictionary with a call to the more expensive description method.
That is, instead "x key/value pairs", you'll see the contents of the dictionary as produced by -[NSDictionary description].
This is the same as typing po dictionary in the console window. Or right clicking the variable and choosing "Print Description". Both of them call the description method of the object.
If you are curious, you can find this formatter at /Developer/Library/Xcode/CustomDataViews/Foundation.plist under the key NSDictionary. What you type as replacement is saved in /Users/USERNAME/Library/Developer/Xcode/UserData/Debugger/CustomDataFormatters and will persist across runs until you delete that file.
A NSDictionary is really a class cluster and few people know the inside structure. At this point you ain't going to find much use for that debugger tree.
This is what you are looking for :
Click on your dict, then click on the little "i" icon :-)
I'm having a bit of a strange issue that I can't quite figure out. I'm somewhat of a n00b to Interface Builder. What I am trying to do seems like it should be simple, but it's not working for some reason.
In interface builder I have a preferences window with a simple NSTextField. I have set the value binding to the Shared User Defaults Controller with the controller key "values" and model key "test". I build/run my app and open the preferences window, type some random value into said text field, close the window. Command-Q the app. Then in a shell i do a "defaults read com.xxx.yyy" for my app and the key and value are nowhere to be found. That being said, it seems like the next time I fire up the app and change the value it works but only if I switch focus off of the NSTextField before closing the window.
In the documentation for NSUserDefaults it says that the shared controller saves values immediately, am I missing something stupid here?
Thanks for any help.
I'm answering this a long time after it was asked in case others find it useful.
It sounds like you need to set "Continuously Updates Values" for the text field you've bound. Otherwise, the value is only sent and, accordingly, the preferences only updated when something happens to 'finalise' the edit. That's usually triggered by pressing Return and probably also happens when you switch focus away from the window (though I just tested this in one of my own applications and it didn't seem to commit the edit).
Is it possible to see the numeric value of an NSNumber in the debugger datatip on in the variable watch window?
I store an Integer value in NSNumber and want to see this value during debugging.
I tried some of the data formatters in the debugger already, but it wasn't much help.
Open the Debugger view and in the Summary column enter
{(int)[$VAR intValue]}
or whatever interpretation is most appropriate for what you want to see in the Debugger.