Python Roguelike: Inventory Disappears - python

Today I progressed further into this Python roguelike tutorial, and got to the inventory. As of now, I can pick up items and use them. The only problem is, when accessing the inventory, it's only visible for a split second, even though I used the console_wait_for_keypress(True) function. I'm not sure as to why it disappears. Here's the code that displays a menu(in this case, the inventory):
def menu(header,options,width):
if len(options)>26: raise ValueError('Cannot have a menu with more than 26 options.')
header_height=libtcod.console_get_height_rect(con,0,0,width,SCREEN_HEIGHT,header)
height=len(options)+header_height
window=libtcod.console_new(width,height)
libtcod.console_set_default_foreground(window,libtcod.white)
libtcod.console_print_rect_ex(window,0,0,width,height,libtcod.BKGND_NONE,libtcod.LEFT,header)
y=header_height
letter_index=ord('a')
for option_text in options:
text='('+chr(letter_index)+')'+option_text
libtcod.console_print_ex(window,0,y,libtcod.BKGND_NONE,libtcod.LEFT,text)
y+=1
letter_index+=1
x=SCREEN_WIDTH/2-width/2
y=SCREEN_HEIGHT/2-height/2
libtcod.console_blit(window,0,0,width,height,0,x,y,1.0,0.7)
libtcod.console_flush()
key=libtcod.console_wait_for_keypress(True)
index=key.c-ord('a')
if index>=0 and index<len(options): return index
return None
I'd appreciate anyone's help or input to this problem.

It may be related to an old version of the library that has an event when you press a key, and another event when you release it. So this could cause it to appear and disappear when you release the key.
So try to see if the screen stays on if you keep the key pressed.

wait_for_keypress does indeed trigger on both press and release events. To fix this, replace wait_for_keypress with the sys_wait_for_event, specifying to trigger only on press events.
Documentation

Related

Get Tkinter to process Arrow Key Input

(I drastically simplified my code now so you should also be able to run it.)
Like I said in the previous version of this question, I am trying to get tkinter to process arrow key strokes. The following code produces a grid of $-signs with one I in the middle (the agent). All it is supposed to do for now is, on pressing the up key, move the agent up and collect a $-sign.
'''
import tkinter as tk
class PlayGame:
def __init__(self):
self.history=[] #Will contain the move history. Each element is a quadruple consisting of the state,action,reinforcement,new state.
self.root=tk.Tk()
for i in range(27):
for j in range(27):
tk.Label(self.root,text='$',height=1,width=3).grid(row=i,column=j)
self.I=[14,14]
tk.Label(self.root,text='I',height=1,width=3).grid(row=14,column=14)
self.root.bind('<KeyPress>',self.onKeyPress)
self.root.mainloop()
def onKeyPress(self,event):
if event.keysym in ['Up','Right','Down','Left']:
if event.keysym=='Up':
tk.Label(self.root,text='',height=1,width=3).grid(row=self.I[0],column=self.I[1])
tk.Label(self.root,text='I',height=1,width=3).grid(row=self.I[0]+1,column=self.I[1])
self.I[0]+=1
'''
It still doesn't work and again, something very weird happened: First, I accidentally had 'row=self.I[0],column=self.I[1]+1' instead of 'row=self.I[0]+1,column=self.I[1]'. The agent would then move to the right when I pressed the up key. After I corrected the mistake, it didn't move at all anymore. But that line can't really be the reason it is not working, can it? Does anyone have an idea why it worked initially, but suddenly not anymore?

Execute Key Sequence on Button Click

I'm trying to create an Undo and Redo Button inside a GUI App using PyQt5 and Python 3.7.
When the Undo and Redo Buttons are clicked, the Key Sequences "Ctrl+Z" and "Ctrl+Y" should be executed respectively. Ive superficially gone through the documentation of QShortCut and QKeySequence but they seem to be designed for detecting key sequences and not triggering them. So how do I implement these buttons?
As per eyllanesc's comment, I'm adding this to better explain what I am trying to achieve.
self.undoButton = self.findChild(QtWidgets.QPushButton, 'undoButton')
self.undoButton.clicked.connect(self.undoButtonPressed)
self.anyPlainTextEdit = self.findChild(QtWidgets.QPlainTextEdit, 'anyPlainTextEdit')
# Function to Execute Key Sequence
def undoButtonPressed(self):
# Execute Ctrl+Z Key Sequence
I'm wondering if this is even possible.
If not, should I maintain Previous and current values of the PlainTextArea in separate variables and set the value of the PlainTextArea accordingly?
You don't have to launch the shortcut to enable redo or undo, just call the slot redo() and undo() when the buttons are pressed:
self.undoButton.clicked.connect(self.anyPlainTextEdit.undo)
self.redoButton.clicked.connect(self.anyPlainTextEdit.redo)

Some questions about switches in python

This is my first Question here at StackOverflow, so please be patient with me if some info isn't present or I missed something important, but anyways i'll do my best :)
Recently I started to code in Python2.7, so I'm not very good at it. While playing with PyGtk, PyGObject, Glade, etc I found something particular about switches (Haven't tried with any other widget, so I don't know if it happens somewhere else. Most likely it doesn't, I hope...)
I made a very basic GUI with a single "window" plus a "switch" using Glade
My objective was to deactivate switch after user tried to activate it if some exeption raised up before, something like:
Activate it --> * Found error --> * Deactivate it
I made some code, and after a while, I noted that THIS piece of code created a loop-like block, blocking GUI's window afterwards:
builder = Gtk.Builder()
window1 = builder.get_object('window')
switchie = builder.get_object('switchie')
switchie.set_active(False)
def Hi(switch, active):
print switchie.get_active()
switchie.set_active(not switchie.get_active())
switchie.connect("""notify::active""", Hi)
window1.set_position(Gtk.WindowPosition.CENTER)
window1.connect("delete-event", Gtk.main_quit)
window1.show_all()
If i'm right, "switchie.connect" links "switchie" object with "Hi" func whenever "switchie" gets clicked.
But if I execute this and try to turn switch on, GUI hangs up. I did try to execute this via script & command-line and adding the "print switch state", resulting in an endless loop (True & False)
I tried with many other funcs I made, but neither of them could solve this issue. In fact, this is the "essence" of all the other funcs I made.
Why does this happen?
Where's the loop?
Am I wrong in some line?
Help is appreciated!
(If you need to see the rest of my faulty funcs, just ask for 'em, but I don't think they'll help...)
You want to hook up the switch like this:
switchie.connect("""activate""", Hi)
This will only get called once for every time it is clicked. What you were doing is hooking up to the signal after it changed, so it was constantly changing, and never catching up. You will also want to change
def Hi(switch, active):
to
def Hi(switch, active = None):
for keyboard support.

how to make EVT_TEXT_ENTER work with EVT_KILL_FOCUS?

I have a text ctrl where user gives number.
once he finished i want to perform an operation.
I know the user finished when the textctrl loses focus or when he press enter.
I did the following:
self.a= wx.TextCtrl(self, -1,style=wx.TE_PROCESS_ENTER)
self.a.Bind(wx.EVT_KILL_FOCUS, self.OnA)
self.a.Bind(wx.EVT_TEXT_ENTER, self.OnA)
def onA(self,event):
print "hello"
event.Skip()
My problem is that if the users click somewhere else with the mouse then eveything works. hello is printed once which means that EVT_KILL_FOCUS happened.
but if uses press enter than hello is printed twice. It means that both EVT_KILL_FOCUS and EVT_TEXT_ENTER happed. I don't want to proccess the event twice.
What can I do?
The simplest answer is not to code for both events.
I would choose EVT_KILL_FOCUS and forget about EVT_TEXT_ENTER and remember to remove the event.Skip()
Edit:
Your problem is that you are mixing a wx.Event (kill-focus) and a wx.commandevent (enter) see: http://wiki.wxpython.org/EventPropagation for further information. The issue here,I think, is that wx.commandevent (Enter) is causing the kill-focus event.
Edit 2:
Assign the events to different functions.
In the function that is used for the EVT_TEXT_ENTER unbind the EVT_KILL_FOCUS, output your error message and then re-bind the EVT_KILL_FOCUS event
i.e.
self.a.Unbind(wx.EVT_KILL_FOCUS)
(do whatever to announce that there is a error here)
self.a.Bind(wx.EVT_KILL_FOCUS, self.OnA)

printing key presses to the screen instantly with python

I know this question is long but what I really want to know is in bold.
I would prefer to use python on Linux.
I'm trying to make a new keyboard layout kind of like devorak but the layout is set to either layout1 or layout2 depending on if you are holding a hot key or not (the hot key should probably be ctrl?)
e.g. press d -> "z" prints to the screen using key layout1
e.g. press ctrl d -> "x" prints to the screen using key layout2
My main problem (and question that needs answering) is the way characters need to print to the screen.
if someone presses the keys (in this order) "(a)(b)(c)(d)(ctrl+d)(shift+e=E)(f)(Enter)"
now lets say the output for these key presses should be "oijzxKb"
I don't want output to render with new lines:
o
i
j
z
x
K
b
I want the characters to appear instantly on the screen as each character is pressed (without waiting for them to press enter).
e.g.
press o
Screenshot1 o
press i
Screenshot2 oi
press j
Screenshot3 oij
.. etc
I assume I will need the following:
a way to read keypresses instantly
a way to print key presses instantly (to the terminal or a GUI or whatever is easiest initially, if it worked on any editor that would be cool!)
I could probably do this in PyGame (but then I probably wouldn't be able to cut and paste etc) and I'm guessing there should be an easier way.
I'm using a Logitech G110 keyboard, I may eventually want to use this as an alternative to my qwerty keyboard on all my applications across all my devices.
Thanks!
EDIT: SOLUTION:
Thanks to the first response,
using Getch from http://code.activestate.com/recipes/134892/
getch = _Getch()
word=""
while True:
c=getch.impl()
if c=="a":
word+="z"
elif ord(c)==127: #backspace
word=word[:-1]
else:
word+=c
print word
This will suffice for now thank you. Once I'm happy with refinement I'll look at doing something lower level, operating system specific without python.
One problem with getch however is that ctrl+a cant be distinguished between ctrl+A (e.g. if you hold ctrl and press keys, it can't tell the difference between upper and lower case)
If it's ok to depends on the X window system, you can use the python-xlib module or the xpyb module to access the X window system and use a XGrabKey call to grab the keyboard related events. Upon each KeyPress event you will be able to print the pressed key.
Now, if you really want to write a keymap, this is totally OS/window system dependent. If you use the X window system (Ubuntu does), you need to check the X documentation about how to write a new keymap. On Ubuntu, the current keymaps definition should be in /usr/share/X11/xkb. Take a look, and try to copy and edit one. You can use setxkbmap to change the current keymap then.
To modify the key mapping of your keyboard, you must use the tools provided by your OS. Most applications don't accept generated events for security reasons.
In your case, that would be xmodmap. Don't forget to create a backup of your current keymap using the -pke option because you will make a mistake - and then, your keyboard won't be working anymore.
If you also want your new keymap work on the console, have a look at the kbd package which changes the keyboard layout at the kernel level.

Categories

Resources