How to create an input box with iron python using windows.forms? - user-interface

For a simple Gui in Iron python I need a simple dialog box with an input text field and OK and cancel button and return value of input text, equivalent to Visual Basic input box.
So basically, dialog pops up, you enter value, hit OK an dialog box closes and returns value to calling function.
I could not find anything in the windows forms library.
I guess you need to create a form yourself from scratch, using text box, etc..?
Is there really no input box in winforms?
If so, could anyone share how to create one with winforms and iron python?
Thanks for help!
Nils

I am new to Ironpython and GUI programming, therefore the following solution might not be elegant neither complete, but it seems to work.
Any ideas for improvement?
import clr
clr.AddReference("System.Windows.Forms")
clr.AddReference("System.Drawing")
from System.Drawing import Point
from System.Windows.Forms import Button, Form, Label, TextBox, FormStartPosition, FormBorderStyle
class MyInputBoxClass(Form):
def __init__(self,message, title, defaultText):
#Creates Input Box with text Input Field
#define form
self.Text = title
self.Width = 600
self.Height = 110
self.StartPosition = FormStartPosition.CenterScreen;
self.FormBorderStyle = FormBorderStyle.FixedDialog
self.MinimizeBox = False;
self.MaximizeBox = False;
#define label
self.label = Label()
self.label.Text = message
self.label.Location = Point(10, 10)
self.label.Height = 30
self.label.Width = 250
#define text box
self.textbox = TextBox()
self.textbox.Text = defaultText
self.textbox.Location = Point(10, 40)
self.textbox.Width = 500
#define button
self.button1 = Button()
self.button1.Text = 'ok'
self.button1.Location = Point(510, 40)
self.AcceptButton = self.button1
#define dialog result
self.button1.DialogResult = DialogResult.OK;
#add controls to form
self.Controls.Add(self.label)
self.Controls.Add(self.textbox)
self.Controls.Add(self.button1)
#Todo: Handel Close Input Box Event
def MyInputBox(message, title, defaultText):
form = MyInputBoxClass(message, title, defaultText)
form.ShowDialog()
#Application.Run(form2) #this is not working, you need ShowDialog for modal form
return form.textbox.Text
def TestGui(analysis_obj):
#This function is beeing called from API
inputTextFromDialogBox = MyInputBox("Please Enter Example Text","ExampleInputBox","Its working but I'm not convinced")
print ("Input Box Return Value is '%s'"%inputTextFromDialogBox)
#ExtAPI.Log.WriteMessage("Input Box Return Value is '%s'"%inputTextFromDialogBox)

Related

Display text on another process' screen (overlay)

I have a question, its more an OS-based one.
I'm playing a video game and I want to be able to put a textual timer ontop of the game's screen as if it was a part of the game itself.
Now, I can write a program in any language that displays a TextBox with a timer on the screen, but if I run it, the game's process (lets call it game.exe) "loses" its focus and I get my TextBox focused and interactive by the OS.
Is there any option to display that text "ontop" of the game.exe that comes from an entire different process? as if there were "layers" to the screen. Also, this text shouldn't be intractable, clickable or make the game.exe process lose its focus.
Here's a very simple example I drew:
Thanks a lot!
Solved this using a window trick with python and tkinter with some windows api stuff.
The trick is to create a transparent non-clickable window and keep it always on top.
I've basically combined this answer with a bunch of simpler stuff like removing window's border and set to auto fullscreen.
from tkinter import *
import time
import win32gui
import win32api
from win32api import GetSystemMetrics
# WIDTH = 500
# HEIGHT = 500
WIDTH = GetSystemMetrics(0)
HEIGHT = GetSystemMetrics(1)
LINEWIDTH = 1
TRANSCOLOUR = 'gray'
title = 'Virtual whiteboard'
global old
old = ()
global HWND_t
HWND_t = 0
tk = Tk()
# tk.title(title)
tk.lift()
tk.wm_attributes("-topmost", True)
tk.wm_attributes("-transparentcolor", TRANSCOLOUR)
tk.attributes('-fullscreen', True)
state_left = win32api.GetKeyState(0x01) # Left button down = 0 or 1. Button up = -127 or -128
canvas = Canvas(tk, width=WIDTH, height=HEIGHT, highlightthickness=0)
canvas.pack()
canvas.config(cursor='tcross')
canvas.create_rectangle(0, 0, WIDTH, HEIGHT, fill=TRANSCOLOUR, outline=TRANSCOLOUR)
canvas.create_text(WIDTH/2,HEIGHT/2,fill="white",font="Arial 20", text="TEXT GOES HERE")
def putOnTop(event):
event.widget.unbind('<Visibility>')
event.widget.update()
event.widget.lift()
event.widget.bind('<Visibility>', putOnTop)
def drawline(data):
global old
if old !=():
canvas.create_line(old[0], old[1], data[0], data[1], width=LINEWIDTH)
old = (data[0], data[1])
def enumHandler(hwnd, lParam):
global HWND_t
if win32gui.IsWindowVisible(hwnd):
if title in win32gui.GetWindowText(hwnd):
HWND_t = hwnd
win32gui.EnumWindows(enumHandler, None)
tk.bind('<Visibility>', putOnTop)
tk.focus()
running = 1
while running == 1:
try:
tk.update()
time.sleep(0.01)
if HWND_t != 0:
windowborder = win32gui.GetWindowRect(HWND_t)
cur_pos = win32api.GetCursorPos()
state_left_new = win32api.GetKeyState(0x01)
if state_left_new != state_left:
if windowborder[0] < cur_pos[0] and windowborder[2] > cur_pos[0] and windowborder[1] < cur_pos[1] and windowborder[3] > cur_pos[1]:
drawline((cur_pos[0] - windowborder[0] - 5, cur_pos[1] - windowborder[1] - 30))
else:
old = ()
except Exception as e:
running = 0
print("error %r" % (e))

Access ListView item text (FMX)

I have a TListView and when the user clicks on the image of an item (big green dot in picture below) i want to copy the item text ("russtest.cfg") and subitem text ("My Device, 1991") to display in a ShowMessage. I can't find how to do it in C++ Builder but this link shows how in Delphi.
Below is the code i've tried in the TListView's ItemClickEx method:
TListItem* item;
item = ListView1->Items->Item[ItemIndex];
UnicodeString s;
s = item->ToString();
ShowMessage(s);
But it brings back this:
EDIT 1: Added the code i use to populate the ListView:
TListViewItem* item2Add = Form1->ListView1->Items->Add();
Form1->ListView1->BeginUpdate();
item2Add->Text = mystring3; // e.g. "russtest.cfg"
item2Add->Detail = mystring2; // e.g. "My Device, 1991"
item2Add->ImageIndex = 1; // big green dot
Form1->ListView1->EndUpdate();
Your need to typecast the TListItem* to TListViewItem*, then you can access its Text property:
TListViewItem* item = static_cast<TListViewItem*>(ListView1->Items->Item[ItemIndex]);
String s = item->Text;
ShowMessage(s);

Link a tkinter button to seperate script

I have a tkinter interface with a few entry widgets as inputs. Upon clicking a button I would like those inputs to be sent to a separate script to be processed and a value printed and potentially returned back to the button (I am looking at this for a dual accuracy assessment statistic)
This is a lower scale example of what I have so far and am looking to accomplish
Example Secondary Script: GUI_ConnectorScript
def calculate():
global result
result = int(entry.get())
result += 1
print result
Primary Script: GUI_ConnectorScript
from Tkinter import *
import GUI_ConnectorScript
background = "#A8A8A8"
master = Tk()
screen_width = master.winfo_screenwidth()
screen_height = master.winfo_screenheight()
width = int(screen_width*0.7)
height = int(screen_height*0.7)
size = "%sx%s"%(width,height)
master.geometry(size)
master.title("GIS Display")
text = Text(master, width = 80, height = 40, background = background)
text.pack(expand = TRUE, fill = BOTH)
entry = Entry(master, width=5).place(x=100,y=100)
button = Button(master, text="Calculate", command=GUI_ConnectorScript).place(x=500,y=500)
mainloop()
I have been trying to figure this out for awhile and have look around a lot for an answer. I have found examples similar but I am having an issue getting it to work for my application.
I agree with Parviz, whenever GUI programs get too complicated you should use Object-Oriented Programming.
I can further advice that you use kivy (if possible) instead of tkinter, its much better for bigger projects

.get() not able to get results of checkboxes

See the following snippet of code:
def choose_ID():
import ttk
global single_ID
id = BooleanVar()
toplevel = Toplevel()
label1 = Label(toplevel, text = "Choose a User ID.", width = 40).pack(anchor=W, pady=5)
for items in range(len(single_ID)):
id = Checkbutton(toplevel, text=single_ID[items], variable=single_ID[items])
id.pack(anchor=W, padx=5)
single_run_but = Button(toplevel, text = "Run", width=10, height=1, command=run_command).pack(anchor=S, pady=5)
id.get()
Its purpose is to open a popup window with a number of checkboxes (the number could be anything from 1 to 100) containing user id's that have been passed to the function from earlier in the script.
The problem is with the id.get() line at the end. When it runs it errors, saying "Checkbutton instance has no attribute 'get'"
What do I need to change to be able to note which of the checkboxes have been checked (it could be only one or multiple boxes)?
Many thanks,
Chris.
The last time you set id is in the for loop. During this, you set id to be a checkbutton, which does not have the get() method.
What you want to do is use the get() method on an IntVar that is associated with the checkbutton through the variable attribute. You can keep references to these variables in a list. I've made a small example of how to dynamically create checkbuttons and still be able to get their values.
from Tkinter import *
def run_command():
selected_ids = []
for i, id_var in enumerate(id_var_list):
if id_var.get():
selected_ids.append(id_list[i])
print selected_ids
root = Tk()
Label(root, text = "Choose a User ID.", width = 40).pack(anchor=W, pady=5)
id_list = ['ID1', 'ID2', 'ID100']
id_checkbutton_list = []
id_var_list = []
for item in id_list:
id_var = IntVar()
id_checkbutton = Checkbutton(root, text=item, variable=id_var)
id_checkbutton.pack(anchor=W, padx=5)
id_var_list.append(id_var)
id_checkbutton_list.append(id_checkbutton)
Button(root, text = "Run", width=10, height=1, command=run_command).pack(anchor=S, pady=5)
root.mainloop()

populating listbox from selection, python

Hi to all that look and might be able to help. I'm new to Python, and to coding in general. I'm working on a program that the basic concept of it is to have a few lists, make a selection from one list, and then another list is populated based on that first choice. I have been able to create the GUI, I've been able to create various different forms of "Listbox", I've been able to follow tutorials that show how to retrieve the indicies of that "Listbox", but I haven't been able to get the 2nd Listbox to fill in with the list I created for a choice made in the 1st box. I've tried checkboxes too, I did get closer on that one, but still no dice.
The supplied code below works in the sense that I can print the 2nd list into the python shell, but when I get a listbox set up in my GUI I can't get it to populate there. Nothing every happens. And I know that I don't have a listbox in this code to have it be populated with the 2nd list. So in this code, I would like the 'brand' choice if 'Apples', to populate the list from 'modelA' in a listbox. Or if the checkboxes actually weren't there and the items in 'brand' where in their own listbox. Any direction might help a lot more than what I've been able to do. Thanks again.
Python 3.3.2
Mac OS X 10.8.5
from tkinter import *
#brand would be for first listbox or checkboxes
brand = ['Apples','Roses', 'Sonic', 'Cats']
#model* is to be filled into the 2nd listbox, after selection from brand
modelA = ['Ants', 'Arrows', 'Amazing', 'Alex']
modelR = ['Early', 'Second', 'Real']
modelS= ['Funny', 'Funky']
modelC= ['Cool', 'Daring', 'Double']
#create checkboxes
def checkbutton_value():
if(aCam.get()):
print("Models are: ", modelA)
if(rCam.get()):
print("Models are: ", modelR)
if(sCam.get()):
print("Models are: ", modelS)
if(cCam.get()):
print("Models are: ", modelC)
#create frame, and check checkbuttons state, print value of model
root = Tk()
aCam = IntVar()
rCam = IntVar()
sCam = IntVar()
cCam = IntVar()
#Checkbutton functions
apples = Checkbutton(root, text = "Apples", variable=aCam, command=checkbutton_value)
apples.pack(anchor="w")
roses = Checkbutton(root, text = "Roses", variable=rCam, command=checkbutton_value)
roses.pack(anchor="w")
sonic = Checkbutton(root, text = "Sonic", variable=sCam, command=checkbutton_value)
sonic.pack(anchor="w")
cats = Checkbutton(root, text = "Cats", variable=cCam, command=checkbutton_value)
cats.pack(anchor="w")
#general stuff for GUI
root.title('My Brand')
root.geometry("800x300")
root.mainloop()
To populate a Listbox based on the selection of another Listbox, you need to bind a method to the 1st Listbox's selection. Here's an example using makes/models of cars:
import Tkinter
class Application(Tkinter.Frame):
def __init__(self, master):
Tkinter.Frame.__init__(self, master)
self.master.minsize(width=512, height=256)
self.master.config()
self.pack()
self.main_frame = Tkinter.Frame()
self.main_frame.pack(fill='both', expand=True)
self.data = {
'Toyota': ['Camry', 'Corolla', 'Prius'],
'Ford': ['Fusion', 'Focus', 'Fiesta'],
'Volkswagen': ['Passat', 'Jetta', 'Beetle'],
'Honda': ['Accord', 'Civic', 'Insight']
}
self.make_listbox = Tkinter.Listbox(self.main_frame)
self.make_listbox.pack(fill='both', expand=True, side=Tkinter.LEFT)
# here we bind the make listbox selection to our method
self.make_listbox.bind('<<ListboxSelect>>', self.load_models)
self.model_listbox = Tkinter.Listbox(self.main_frame)
self.model_listbox.pack(fill='both', expand=True, side=Tkinter.LEFT)
# insert our items into the list box
for i, item in enumerate(self.data.keys()):
self.make_listbox.insert(i, item)
def load_models(self, *args):
selection = self.make_listbox.selection_get()
# clear the model listbox
self.model_listbox.delete(0, Tkinter.END)
# insert the models into the model listbox
for i, item in enumerate(self.data[selection]):
self.model_listbox.insert(i, item)
root = Tkinter.Tk()
app = Application(root)
app.mainloop()

Resources