Editing text from outside shoes app overlaps text - ruby

I am working on a ruby app that needs to update text on the GUI at unknown times. The process I am using overlaps the text with text from the previous edit.
class_text is the element I need to edit. I have about 8 different places in the program that could potentially change the text. Sometimes when the text is changed the previous text does not get removed and instead the text overlaps itself.
$class_text.text = "Nothing scheduled to take attendance at this time."
This project was started by people before me and this is my first experience with Ruby. Thank you for any info you can send my way!

without more specific information I've just tested a bare minimum for a scenario similar to yours (using Red Shoes though) and this works:
Shoes.app do
#test_stack = stack do
#edit_box = edit_box
#edit_box.text = "first text"
#edit_text = para "second text"
end
button "change" do
#edit_box.text = "first replacement"
#edit_text.text = "second replacement"
end
end
You could also try clearing the element first.
hth
seba

Related

Ruby Watir reference Chrome Print Preview

I'm writing a script to cycle through some links and print to PDF.
When you click on one of the links a new window pops up of the document to be printed and on top of that new window Chrome's print preview box pops up.
I'm trying to change the printer and then click the print button.
What's happening with my code however is that watir is only looking at the window html and not the print preview html so the elements are unable to be located.
My code looks like this:
begin
browser.window(title: 'Window Title Name').use do
browser.div(:id => "navbar-scroll-container").button(:class => "destination-settings-change-button").click
sleep(1)
browser.element(:title => "CutePDF Writer").click
browser.button(:visible_text => 'Print').click
end
rescue Watir::Exception::NoMatchingWindowFoundException
retry
end
I have tried using just "browser.windows.last.use do" instead of the title name but that also doesn't work.
I know it can only see the underlying window's html because when I puts browser.html the output is that underlying windows html.
If you want to look at the html situation just Ctrl+P this page (in chrome) to see what I mean.
Of course, after posting a question I soon found a sort of answer; basically chrome opens 2 browser windows and the print preview one couldn't be accessed by title (because it had the same title as the underlying one) but could be accessed by browser.window(:index => 1).use do. not sure why browser.windows.last.use do didn't work. Also following that I would have thought browser.window(:index => 2).use do would have been the correct one as index 0 would be the originally opened one, index 1 the popup and index 2 the print preview.

Tkinter entry widget lags while typing. How to update typed text in real time?

Using python3. I'm new to tkinter writing a program with a GUI that takes some input parameters and does some data processing, so it needs entry boxes where I can type numbers in.
I cannot for the life of me figure out how to get the entry boxes to stop lagging, i.e: when a box is clicked on and typed into, the changes made to the text in that entry box don't appear until I click on another button or text box in the window. Functionally, the program still works like this but it's irritating not being able to see what I'm typing and others will eventually use this software.
I've gotten halfway to fixing the problem by putting in event bindings so that key presses trigger an update of the idle tasks. The text now updates while typing, but it's "one letter slow" (a typed letter appears only after the next letter is typed) and this is still not ideal.
Help?
MWE:
from tkinter import *
###Window: 'top'
top = Tk() #make window
top.geometry("670x360") #window size
top.wm_title("Test program for TKinter")#window title
#window and label background colour
bgcol='light sea green'
top.configure(background=bgcol) #set colour
#events to refresh window
def keypress(event):
print('key pressed')
#update all idle widgets (remove text box lag)
top.update_idletasks()
def mouseentry(event):
print('mouse entered text box')
#update all idle widgets (remove text box lag)
top.update_idletasks()
##text entry box
Label(top,background=bgcol, text="").pack() #spacing label
v = StringVar()
e=Entry(top, width=50, textvariable=v)#,height=1)
e.pack()
Label(top,background=bgcol, text="").pack() #spacing label
v.set("a default value")
s = e.get()
e.bind("<Key>",keypress)
e.bind("<Enter>",mouseentry)
#Label displaying text box contents (not working right now, not important)
Label(top,background=bgcol, textvariable=s).pack() #text display label
#make buttons appear on start
top.update()
top.mainloop()
How do I update the entry widget as it is typed? Is there something really simple that I'm overlooking?
Answer to own question:
Mainloop wasn't running in the background (or something) of my python install, for whatever reason, whether run via Anaconda or via the terminal.
Simple reinstall of Anaconda IDE with python3.4 fixed all my issues.

PyQt QComboBox.setEditText leaves the entered text selected/highlighted; how to unhighlight?

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

Running a Ruby class from a Shoes Edit Line

Hello All,
I have finished writing up a Ruby class to complete exactly what it is supposed to, but since it is Ruby, I have been running it through my terminal and I need this to be more user-friendly (i.e. have a GUI). So I googled this and came across Shoes, which seems to be a nice Ruby GUI toolkit, and exactly what I am looking for. However, despite my googling I can't seem to figure out how to use a Shoes GUI edit line to send an argument to the class I made. Here is the edit line
Shoes.app do
background white
para "Application Name"
stack(margin: 12) do
para "Message"
flow do
edit_line
button "Enter"
end
end
end
In short, is there some way to do a gets.chomp (or literally anything else that is similar) with this and set it equal to an instance variable?
Yes! Just assign the elements you want to keep track of to instance variables, and pass a block to the button (the block gets executed when the button is clicked). Try this:
Shoes.app do
background white
para "Application Name"
stack(margin: 12) do
#message = para "Message"
flow do
#edit_line = edit_line
button "Enter" do
#message.text = #edit_line.text
end
end
end
end

How do I know which element has the focus?

How do I know which element has the focus, or how to determine whether the focus of a particular element?
I don't know of anyway to query for this kind of information directly. I suppose you could traverse the DOM and check for it manually. If that's the case you should look at this.
Perhaps what you are trying to do can be achieved by handling an event when specific elements of interest gain focus. Here is how you would do that in jQuery.
$('<selector>').focus(function() {
// Do something here
});
Just for giggles, here is one way you could use the focus method to track which element recieved it last. I highly recommend against using this code.
var gotDaFocus;
$('*').focus(function() {
gotDaFocus = this;
});
not yet implemented yet i'm afraid.
You could do something like this
Shoes.app do
#focused = para ""
stack do
#label1 = edit_line :text => 1
click do
#focused.replace #label1.text
end
end
stack do
#label2 = edit_line :text => 2
click do
#focused.replace #label2.text
end
end
end
But the problem in windows is that the controls steal all the event from Shoes.
In Green Shoes it would work. If you'r in windows you can still see the result if you click just to the right of the edit_line. Of course, this is only when you click with the mouse, you should check keypress tot get the keyboard events also.
Grtz

Resources