My app has a GtkFileChooserButton that you can use to open a chooser widget and pick a single file .. and then perform operations on that file. This works.
I've added drag & drop functionality to the button as well. It works, but it's buggy.
In short, the first dnd to the FileChooserButton triggers the file-set signal and appears to have worked, -- the name changes from "( None )" to the file's name and if you then click on the button, it pops up a chooser widget showing the proper file selected; HOWEVER, as you can see from the debug output below, get_filename() does not return the filename! Not the first time, anyway.
The second time we dnd a file onto the button (whether it's a different file or the same file again), all goes well and get_filename() returns the file's name. Why?
Here's the debug output from my program when I drag three files on to the button, one at a time:
[on_file-set] FileChooserButton.get_filename() output:
None
[on_file-set] FileChooserButton.get_filename() output:
'/home/ryran/Desktop/priv.txt'
[on_file-set] FileChooserButton.get_filename() output:
'/home/ryran/Desktop/kinamppost'
PS: When I did this, the 1st and 2nd dnd were actually the same file.
If you want to see the full app in action, it's at http://github.com/ryran/pyrite, and I'd love to post code, but there's not really anything to post!! I'm not doing drag_dest_set() because FileChooserButton already supports dnd. So ALL I'm doing is defining a cb for the FileChooserButton's file-set signal. So uhh.. here's that:
def action_chooserbtn_file_set(self, widget):
print "[on_file-set] FileChooserButton.get_filename() output:\n{!r}\n".format(widget.get_filename())
For the record I also tried doing all this in concert with defining drag_dest_set, but came up with the same results.
What else to say? I'm starting to think this is a bug.
Turns out this really is a GTK+ bug. Talked to a developer on IRC. He helped me realize that and then encouraged me to post a bug report, which I did -- https://bugzilla.gnome.org/show_bug.cgi?id=669718
Related
first of all let me start off by saying I started coding around 6 weeks ago in self-study, so it is very likely, that the approach may still be a total mess.
I have a program running (fine for me) in cli, but I want to make it usable for people that faint, when they see plain white text on a black background which they have to operate without a mouse.
Besides my main window, which is running in the background I wanted to have a message window, which displays the information if all necessary files where selected. which is shown below.
files_to_open = {'File_1':'', 'File_2':'', 'File_3':''}
def selectfiles_window():
global message_window
message_window = Tk()
...
content = Label(message_window, text=get_open_file_status_txt(), **txt_status_general)
content.pack(side='top')
button_select_file1 = Button(message_window,text = 'File 1',font = txt_general['font'],command = lambda:(
select_file_action(name='File 1', filetypename='Excel workbook', extension='*.xlsx'),
content.configure(text=get_open_file_status_txt())))
button_select_file1(side='bottom')
message_window.mainloop()
def select_file_action(name, filetypename, extension):
global files_to_open
files_to_open[name] = filedialog.askopenfilename(title = f'Select {name}', filetypes=[(filetypename, extension)])
def get_open_file_status_txt():
global files_to_open
message =f'''
[File_1] is {"NOT SET" if (files_to_open["File_1"] == "") else "SET"}'''
return message
I expected, that the text is updated after the filedialog was closed (which is partly working as expected).
Now what I don't understand: If I click the button to select File_1 and cancel it for the first time, the value for key File_1 is set to (). Any time after that, if I click the button to select File_1 and cancel it, the value for key File_1 is set to ''. If I select a file the path is saved correctly as value (also on the first attempt). If I cancel it is set again to ''.
Anybody an idea about why the value is set to () on the first cancel but afterwards runs as expected?
I would also be grateful for a different solution to update the text, if my approach is totally off.
Thank you and best regards,
Thomas
Turns out, that the function call was not the issue, rather that it is a (strange to me but maybe intended) behavior of filedialog.askopenfilename, which returns an empty tuple if cancel is selected on first call but an empty string on every further canceled calls.
I am following Chapter 18 of Automate the Boring Stuff with Python. I'm on OS X.
I am trying to use pyautogui to click on a text input or text document and then input text.
I am entering the following into a shell ((370, 80) are the coordinates of my Chrome address bar):
pyautogui.click(370,80); pyautogui.typewrite('Hello world!')
click() seems to not be working as expected. It will highlight text in an input when I click on the input, but even when I manually type after the click, the text shows up in the shell. See the below screenshot of the result of running the above line:
Other methods like position, moveTo, moveRel, and dragTo are working as expected.
If I run time.sleep(5); pyautogui.typewrite('test') and manually click on the text document or input while the thread is sleeping, the text is inputted as desired.
What might be the problem?
Turns out there is a bug related to click() in OSX. Here is the solve:
Open the __init__.py file in the pyautogui package directory (find the location of your Python packages using this answer.
On line 510 (in the click() function), change the fourth argument to platformModule._multiClick() from 3 to clicks (no quotes). So the correct invocation is platformModule._multiClick(x, y, button, clicks)
Save the edited file.
There is an open PR to fix the issue.
I have a wxPython gui that sometimes has weird behavior. I have a button that creates a dialog, then calls dia.Show() and dia.Center(). At this point dia.IsShownOnScreen, dia.IsActive, and dia.Shown are all "true", but the dialog is actually nowhere to be found.
Does anyone know any reasons why IsShownOnScreen would come up as true, but be incorrect?
I am trying to isolate this problem in the code, but the codebase is large and this problem may take a while to reproduce.
Any help is appreciated.
Edit:
If the following code is not run while initializing, my dialog window shows up without a problem:
TEXT="choose directory. No spaces are allowed in path!"
dia = wx.DirDialog(self, message=TEXT,defaultPath = os.getcwd() ,style=wx.DD_DEFAULT_STYLE )
result=dia.ShowModal()
if result == wx.ID_OK:
self.WD=str(dia.GetPath())
dia.Destroy()
This piece of code is used if the user runs:
$ program.py
instead of specifying a directory in the command line:
$ program.py -WD directory
The code above has no obvious relationship to the button and dialog in the main frame of my gui, but this code is definitely what is breaking things.
I am trying to configure my text file viewer to open files by dragging them onto it. I've looked at several tutorials and tried to imitate them, but my widget never seems to be receiving the "drag_data_received" signal. Here, self.topLevel is a gtk.Window widget, the root of my application, and this is the last bit of the code for setting it up. I've confirmed that dragging text files onto it doesn't call OnDrop at all.
def OnDrop(widget, context, x, y, sel, targetType, timestamp):
print context.actions
print context.targets
return True
self.topLevel.connect("drag_data_received", OnDrop)
self.topLevel.drag_dest_set(gtk.DEST_DEFAULT_DROP |
gtk.DEST_DEFAULT_MOTION |
gtk.DEST_DEFAULT_HIGHLIGHT, [("text/*", 0, 0)], gtk.gdk.ACTION_COPY)
self.topLevel.show_all()
I realized that my application was getting the signal, but the TextView widget that I was dropping everything onto (because it occupied most of its window) was absorbing these signals and not calling my callback function; dropping the file onto any other part of the application fixed it. I got it to work by calling the TextView's drop_dest_unset function.
This is related to another question I found here that seems to be inactive for a few months, so I think it's worth asking again.
I have created a simple QDialog that has a QTextEdit and a QPushButton. This pops up in my application when a user right-clicks and selects the option to "add comments". I want them to be able to write free-form text and I'll just save whatever they write as a long string with no concern for new lines, etc.
When the user clicks the button, it executes code like this:
self.connect(accept_button,QtCore.SIGNAL('clicked()'),lambda arg=str(view_textedit.toPlainText()): self.updateGroupComments(arg))
def updateGroupComments(self,new_comment_str):
print "Updating user comment to have new string: " + new_comment_str
self.group_entry.list_of_user_comments[self.currentFrameCounter] = new_comment_str
This is not detecting the TextEdit text that is visible (it only detects whatever the text edit text is set to when it is created). How do I make a simple command that returns the currently visible text from a QTextEdit. Again, the function
toPlainText()
is not working correctly... it doesn't find the currently visible text, only whatever text was on screen before changes or additions started being made by the user.
If this can't be done without subclassing and appealing to cursor positions, it makes the whole thing seem worthless... so please keep suggestions only to those implemented without subclassing or manipulating cursors. It should be really simple and straightforward to just return all currently visible text... what am I missing?
Objects that are being bound to default arguments are evaluated at the definition time. The function is working correctly, it returns whatever was in the text field when it was executed. Your code simply calls it at the wrong moment. If you want to use lambda, then do:
self.connect(
accept_button, QtCore.SIGNAL('clicked()'),
lambda: self.updateGroupComments(str(view_textedit.toPlainText()))
)
Or make view_textedit an instance attribute instead, and do simply
self.connect(
accept_button, QtCore.SIGNAL('clicked()'), self.updateGroupComments
)
And change updateGroupComments to call self.view_textedit.toPlainText instead of taking an argument.
BTW, this is not PyQt specific, this is how Python works in general.
To illustrate my last comment, that lambda can very well be replaced with:
def slot():
self.updateGroupComments(str(view_textedit.toPlainText()))
self.connect(accept_button, QtCore.SIGNAL('clicked()'), slot)