Seite 1 von 2
Slotmachine/ Zahleneingabe via Pfeiltasten
Verfasst: Mittwoch 1. Februar 2012, 20:51
von Pete
Hallo zusammen,
ich muss ein gut funktionierendes ökonomisches Experiment erweitern, damit wir es in einem Hirnscanner laufen lassen können. Das bringt mit sich, dass die Eingabe von Zahlenwerten ausschließlich über die Pfeiltasten möglich ist. Damit das funktioniert möchten wir eine Art "Slotmachine" implementieren: Es wird eine zufällige ganze Zahl zwischen 10 und 75 gezogen und zunächst ist die erste Stelle der Zahl aktiv. Mit Pfeil hoch/runter lässt sich dann die 10er-Zahl ändern. Mit Pfeil rechts/links zwischen 10er und 1er Block wechseln. Ist man auf dem 1er Block und drückt ein weiteres mal "rechts", so zählt das als Eingabe und die Zahl wird an den Server gesendet.
Bisher sieht es in unserem Client wie folgt aus:
Code: Alles auswählen
elif data == "@end \n":
button.config(state = NORMAL)
entry.destroy()
entry = Entry(root, width=12, font = ("Helvetica", "20"))
entry.focus_set()
entry.insert(0, "$")
entry.pack()
id_ = entry.bind('<Return>', lambda _: root.quit())
root.mainloop()
entry.unbind("<Return>", id_)
str = entry.get()
entry.delete(0, END)
root.update()
sock.send(str[:+10] + " \n")
Sprich, wir haben bisher ein entry widget verwendet und die Versuchspersonen ganz normal via Zahlentasten & Enter-Taste das Experiment bedienen lassen. Die Frage ist jetzt, wie ich vorgehen soll, um das auf die Pfeiltasten zu übertragen.
Ich dachte mir, via entry einfach Zufallszahlen einzufügen und zusätzlich ein paar weitere bind-commands zu bilden. Aber irgendwie möchte das nicht so ganz hinhauen. Was meint ihr?
Die besten Grüße
Pete
Re: Slotmachine/ Zahleneingabe via Pfeiltasten
Verfasst: Mittwoch 1. Februar 2012, 21:05
von BlackJack
@Pete: Also ich meine das ist ein ganz ekliger Weg um sich um ereignisbasierte Programmierung zu drücken. In *dem* Stil würde ich das nicht programmieren und auch niemandem empfehlen.
Re: Slotmachine/ Zahleneingabe via Pfeiltasten
Verfasst: Mittwoch 1. Februar 2012, 21:51
von Pete
Hi BlackJack,
vielen Dank für deine schnelle Antwort. Das Ding ist, dass das nur ein kleiner Teil eines deutlich größeren Programms ist (ca. 2,000 Zeilen) und ich mich bei weitem nicht gut genug auskenne, um zu sehen, welche Auswirkungen eine Änderung auf das ganze weitere Programm haben würde. Ich hab keine Ahnung, was ereignisbasierte Programmierung ist, aber wenn du mir ein paar Anhaltspunkte gibst, wie ich das Problem einigermaßen schnell lösen könnte, wäre ich dir sehr dankbar
LG
Pete
Re: Slotmachine/ Zahleneingabe via Pfeiltasten
Verfasst: Mittwoch 1. Februar 2012, 21:57
von BlackJack
@Pete: Wenn das ganze Programm so aufgebaut ist, dann kenne ich keine schnelle Lösung, weil man es dann umschreiben müsste, und dazu müsste man es halbwegs vollständig verstanden haben.
Re: Slotmachine/ Zahleneingabe via Pfeiltasten
Verfasst: Mittwoch 1. Februar 2012, 22:04
von Pete
Hmmm, ja so etwas hatte ich schon fast befürchtet. Das ganze Programm umschreiben ist aber zeitlich nicht wirklich realistisch. Gibt es denn keine Möglichkeit, wie man eine im entry widget präsentierte Zahl als tatsächliche Zahl verwenden und deren erste bzw. zweite Ziffer separat markieren & ändern kann?
Danke
Pete
Re: Slotmachine/ Zahleneingabe via Pfeiltasten
Verfasst: Donnerstag 2. Februar 2012, 22:22
von theo.puke
1. Du kannst ja versuchen, den Teil in C++/C#/Java etc. zu schreiben, da diese Sprachen NumericUpAndDown Komponenten besitzen, die die Programmierung von so etwas ziemlich erleichtern.
2. Oder du baust noch zwei Buttons (plus und minus) unter jedes Entry und ersetzt dadurch die Pfeiltasten...
Ersteres durfte wahrscheinlich leichter sein...
Bei mir sieht das jetzt so aus:
C#:
Code: Alles auswählen
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
int zehner;
int Zehner
{ set
{ zehner = value;} get {return zehner*10;}}
int Einser;
public Form1()
{
InitializeComponent();
DisableAllSecond();
}
private void button1_Click(object sender, EventArgs e)
{
Zehner = (int)numericUpDown1.Value;
EnableAllSecond();
}
private void EnableAllSecond()
{
numericUpDown2.Enabled = true;
button2.Enabled = true;
label2.Enabled = true;
}
private void DisableAllFirst()
{
numericUpDown1.Enabled = false;
button1.Enabled = false;
label1.Enabled = false;
}
private void DisableAllSecond()
{
numericUpDown2.Enabled = false;
button2.Enabled = false;
label2.Enabled = false;
}
private void button2_Click(object sender, EventArgs e)
{
DisableAllFirst();
Einser = (int)numericUpDown2.Value;
DisableAllSecond();
label4.Text = (Einser + Zehner).ToString();
}
Funktioniert perfekt... Nur schade, dass ich keine Bilder hochladen kann ):
Re: Slotmachine/ Zahleneingabe via Pfeiltasten
Verfasst: Freitag 3. Februar 2012, 10:48
von lunar
@theo.puke: Mit der Sprache hat das nichts zu tun. Das Problem des OP ist weder das Toolkit, noch die Sprache, sondern die Struktur des existierenden Quelltexts. Der Wechsel der Sprache ist ohnehin keine Lösung, wenn der OP das Programm schon in Python nicht neu schreiben kann.
Dein C#-Beispiel ist ohne die Resourcen-Datei des Designers nutzlos, weil unvollständig. So würde man das auch nicht entwickeln.
Re: Slotmachine/ Zahleneingabe via Pfeiltasten
Verfasst: Freitag 3. Februar 2012, 16:53
von theo.puke
@ lunar Nein! Der Code im Designer ist nicht so *wichtig*. Der wird in VC# automatisch generiert, wenn du Komponenten auf die Oberfläche ziehst. Deswegen wollte ich ja ein Bild hochladen, das meine Oberfläche zeigt.
Edit
Aber mit dem Sprachenwechsel gebe ich dir recht, das ist sinnlos.
Re: Slotmachine/ Zahleneingabe via Pfeiltasten
Verfasst: Freitag 3. Februar 2012, 17:01
von Hyperion
theo.puke hat geschrieben:@ lunar Nein! Der Code im Designer ist nicht so *wichtig*. Der wird in VC# automatisch generiert, wenn du Komponenten auf die Oberfläche ziehst. Deswegen wollte ich ja ein Bild hochladen, das meine Oberfläche zeigt.
Und wie sollte der OP oder jemand anderes Deinen Code testen? Müssen wir dann also noch selber "die" Komponenten auf die Oberfläche ziehen? So unwichtig ist die Datei also nicht...
Und wenn Du ein Bild hochladen wolltest, wieso hast Du es nicht getan?
Re: Slotmachine/ Zahleneingabe via Pfeiltasten
Verfasst: Freitag 3. Februar 2012, 17:08
von theo.puke
@Hyperion Ja du hast ja Recht, indem du sagst, die Datei ist wichtig. Wie läd man hier Bilder hoch?
Re: Slotmachine/ Zahleneingabe via Pfeiltasten
Verfasst: Freitag 3. Februar 2012, 17:09
von Hyperion
theo.puke hat geschrieben:
Wie läd man hier Bilder hoch?
Du kannst sie nicht direkt hier hochladen, sondern nur auf eine externe URL verlinken. Ich benutze dafür ImageShack, es gibt da ja aber dutzende Anbieter von Bilderhostern.
Re: Slotmachine/ Zahleneingabe via Pfeiltasten
Verfasst: Freitag 3. Februar 2012, 17:15
von theo.puke
Gut gut... Dann werde ich mich mal auf die Suche machen.
Re: Slotmachine/ Zahleneingabe via Pfeiltasten
Verfasst: Dienstag 7. Februar 2012, 19:59
von problembär
Pete hat geschrieben:Das bringt mit sich, dass die Eingabe von Zahlenwerten ausschließlich über die Pfeiltasten möglich ist. Damit das funktioniert möchten wir eine Art "Slotmachine" implementieren: Es wird eine zufällige ganze Zahl zwischen 10 und 75 gezogen und zunächst ist die erste Stelle der Zahl aktiv. Mit Pfeil hoch/runter lässt sich dann die 10er-Zahl ändern. Mit Pfeil rechts/links zwischen 10er und 1er Block wechseln. Ist man auf dem 1er Block und drückt ein weiteres mal "rechts", so zählt das als Eingabe und die Zahl wird an den Server gesendet.
"Mach' das nicht, Du alter Drückeberger und wieso schreibst Du überhaupt in Python?"
So'n Blödsinn, was sind das nur wieder für Antworten hier???
Mein Vorschlag wäre ein Scale-Widget, das hat automatisch Support für die Hoch-/Runtertasten:
Code: Alles auswählen
#!/usr/bin/env python
# coding: iso-8859-1
import Tkinter
def theEnd(scale, mw):
print scale.get()
mw.destroy()
mw = Tkinter.Tk()
scale = Tkinter.Scale(mw,
from_ = 10,
to = 75,
orient = Tkinter.VERTICAL,
label = "Pick a number, then press Return:")
scale.bind('<Return>', lambda x: theEnd(scale, mw))
scale.focus()
scale.set(42)
scale.pack()
mw.mainloop()
Warum soll man das nicht machen, wenn Tkinter dafür schon eine fertige Lösung bietet?
Re: Slotmachine/ Zahleneingabe via Pfeiltasten
Verfasst: Dienstag 7. Februar 2012, 21:31
von BlackJack
@problembär: Du solltest vielleicht nochmal die Problemstellung und den bereits vorhanden Quelltext, in den die Lösung eingebaut werden soll, betrachten. Deine Lösung ist keine. Jedenfalls nicht für diese Vorgaben.
Re: Slotmachine/ Zahleneingabe via Pfeiltasten
Verfasst: Mittwoch 8. Februar 2012, 13:06
von wuf
theo.puke hat geschrieben:Gut gut... Dann werde ich mich mal auf die Suche machen.
Danke. Wäre Super wenn du uns doch noch ein Bildchen deiner Anwendung zeigen könntest.
Gruß wuf

Re: Slotmachine/ Zahleneingabe via Pfeiltasten
Verfasst: Mittwoch 8. Februar 2012, 23:20
von problembär
BlackJack hat geschrieben:@problembär: Du solltest vielleicht nochmal die Problemstellung und den bereits vorhanden Quelltext, in den die Lösung eingebaut werden soll, betrachten. Deine Lösung ist keine. Jedenfalls nicht für diese Vorgaben.
Du meinst wohl die zwei Stellen (für 10er und 1er), bei denen man mit den Pfeiltasten hin- und hersteuern kann. Sehe ich eigentlich keinen Sinn drin, aber na gut, das wäre dann eben z.B. so:
Code: Alles auswählen
#!/usr/bin/env python
# coding: iso-8859-1
import Tkinter as tk
import random
class SlotScale(tk.Scale):
def __init__(self, nr, master, defaultvalue, label):
self.nr = nr
self.master = master
self.defaultvalue = defaultvalue
self.label = label
tk.Scale.__init__(self,
self.master,
from_ = 0,
to = 9,
orient = tk.VERTICAL,
label = self.label)
self.set(self.defaultvalue)
self.bind('<Left>', self.master.changeToLeft)
self.bind('<Right>', self.master.changeToRight)
self.pack(side = tk.LEFT)
class Slot(tk.Frame):
def __init__(self, master):
tk.Frame.__init__(self, master, relief = tk.RIDGE)
self.master = master
self.defvalues = self.getDefValues()
self.scale1 = SlotScale(1, self, self.defvalues[0], "10s")
self.scale2 = SlotScale(2, self, self.defvalues[1], "1s")
self.scale1.focus()
self.focuson = 1
self.pack(padx = 20, pady = 20)
def getDefValues(self):
r = random.randrange(75) + 1
return (r // 10, r % 10)
def changeToLeft(self, event):
if self.focuson == 2:
self.scale1.focus()
self.focuson = 1
def changeToRight(self, event):
if self.focuson == 1:
self.scale2.focus()
self.focuson = 2
else:
self.process()
def process(self):
print self.scale1.get() * 10 + self.scale2.get()
self.master.destroy()
mw = tk.Tk()
mw.bind_class("Scale", "<Left>", lambda e: None)
mw.bind_class("Scale", "<Right>", lambda e: None)
slot = Slot(mw)
mw.mainloop()
Das ".bind_class()" an der Stelle ist leicht unsauber, weil es sich auch auf andere Scale-Widgets auswirkt, die die Anwendung gegebenenfalls haben könnte, siehe den Abschnitt "Instance and Class Bindings" in dem Dokument
hier.
Ich würde mich über einen Verbesserungsvorschlag dahingehend freuen, daß nur in dem konkreten "SlotScale"-Widget das zusätzliche Verhalten der Links-/Rechts-Pfeiltasten (Verminderung, bzw. Erhöhung des Scale-Wertes) ausgeschlossen wird, also jeweils nur die ".changeToLeft()", bzw. ".changeToRight"-Methode des übergeordneten "Slot"-Widgets aufgerufen wird, wie es jetzt schon - wie gesagt leicht unsauber - realisiert ist.
Re: Slotmachine/ Zahleneingabe via Pfeiltasten
Verfasst: Donnerstag 9. Februar 2012, 12:00
von wuf
theo.puke hat geschrieben:Du kannst ja versuchen, den Teil in C++/C#/Java etc. zu schreiben,
Ich beherrsche diese Sprachen leider nicht. Habe einmal versucht nach den Vorgaben von 'Pete', die noch nicht präzise genug sind, etwas in Tkinter & Python zusammen zu basteln:
Skript ausgelagert!
Gruß wuf

Re: Slotmachine/ Zahleneingabe via Pfeiltasten
Verfasst: Donnerstag 9. Februar 2012, 17:49
von problembär
@wuf: Hab' kein functools (Py 2.4), geht aber auch ohne, mit der Änderung zu:
Code: Alles auswählen
button_up = tk.Button(left_frame,
text=BUT_UP, command = lambda arg = BUT_UP: self.callback(BUT_UP))
button_up.pack(fill='both')
Jedoch: Leider erhalte ich bei Dir keine Reaktion mit den Pfeiltasten.

Re: Slotmachine/ Zahleneingabe via Pfeiltasten
Verfasst: Donnerstag 9. Februar 2012, 18:11
von Hyperion
problembär hat geschrieben:@wuf: Hab' kein functools (Py 2.4), ...
Dann solltest Du aber wirklich mal auf 2.7 updaten

Re: Slotmachine/ Zahleneingabe via Pfeiltasten
Verfasst: Donnerstag 9. Februar 2012, 18:30
von problembär
@Hyperion: Hab' ich mal versucht, hatte unerwartete Effekte: "Never change a running system."

-----
Man braucht noch nicht mal Scale, es geht sogar mit einem einfachen Label. Ich finde es so eigentlich sogar noch eleganter:
Code: Alles auswählen
#!/usr/bin/env python
# coding: iso-8859-1
import Tkinter as tk
import random
class SlotLabel(tk.Label):
def __init__(self, master, defaultvalue):
self.master = master
self.value = defaultvalue
self.var = tk.Variable()
self.var.set(str(self.value))
tk.Label.__init__(self,
self.master,
font = "Arial 22",
fg = 'black',
bg = 'white',
borderwidth = 3,
textvariable = self.var)
self.bind('<Up>', self.increaseValue)
self.bind('<Down>', self.decreaseValue)
self.bind('<Left>', self.master.changeToLeft)
self.bind('<Right>', self.master.changeToRight)
self.pack(side = tk.LEFT, padx = 5)
def increaseValue(self, event):
if self.value < 9:
self.value += 1
self.var.set(str(self.value))
def decreaseValue(self, event):
if self.value > 0:
self.value -= 1
self.var.set(str(self.value))
def enableFocusRidge(self):
self.configure(relief = tk.SOLID)
def disableFocusRidge(self):
self.configure(relief = tk.FLAT)
class Slot(tk.Frame):
def __init__(self, master):
tk.Frame.__init__(self, master)
self.master = master
self.defvalues = self.getDefValues()
self.label1 = SlotLabel(self, self.defvalues[0])
self.label2 = SlotLabel(self, self.defvalues[1])
self.label1.focus()
self.label1.enableFocusRidge()
self.focuson = 1
self.pack(padx = 20, pady = 20)
def getDefValues(self):
r = random.randrange(75) + 1
return (r // 10, r % 10)
def changeToLeft(self, event):
if self.focuson == 2:
self.label1.enableFocusRidge()
self.label2.disableFocusRidge()
self.label1.focus()
self.focuson = 1
def changeToRight(self, event):
if self.focuson == 1:
self.label1.disableFocusRidge()
self.label2.enableFocusRidge()
self.label2.focus()
self.focuson = 2
else:
self.process()
def process(self):
print int(self.label1.var.get()) * 10 + int(self.label2.var.get())
self.master.destroy()
mw = tk.Tk()
slot = Slot(mw)
mw.mainloop()