I'm trying to use a "haze" character - ACS_CKBOARD - as a background, with a custom foreground and background color.
This appears to work okay, but when I call addstr to show text on top of the background, the text is garbled. It appears to be a selection of "alternate characters" in place of my "Hello, world!", except of course that some few normal letters show through.
Here's a small screen capture:
I'm assuming that something has jammed up inside curses. Does anyone know how I can get the correct text to display against this background?
Here's some code that produces the behavior:
import curses
import locale
def main(scr):
curses.init_color(2, 650, 407, 160) # brown
curses.init_color(6, 149, 113, 78) # tan
curses.init_pair(1, 2, 6)
scr.bkgd(curses.ACS_CKBOARD, curses.color_pair(1))
scr.clear()
scr.addstr(10, 0, 'Hello, world!', curses.color_pair(0))
scr.getch()
if __name__ == "__main__":
locale.setlocale(locale.LC_ALL, '')
curses.wrapper(main)
FWIW: I'm using iTerm2 on a Mac, Python version 3.5.3. If I run the same code in Terminal, I get a similar result with the wrong color:
Update:
After reading Thomas Dickey's answer, I tried to implement what he suggested. I tried setting the bkgd followed by both clear and erase followed by another call to set the bkgd. That didn't work- I got the color without the background characters. Looking at the documentation for bkgd, it does specify that "The change is then applied to every character position in that window", so that's right out!
Then I found window.bkgdset(char[, attr]), which does not immediately apply it's setting to every character position. Instead, it just applies to newly-drawn bits. With that function, I modified my code as follows:
curses.init_pair(1, 2, 6)
scr.bkgd(curses.ACS_CKBOARD, curses.color_pair(1))
scr.erase()
scr.bkgdset(' ', curses.color_pair(1))
scr.addstr(10, 0, 'Hello, world!', curses.color_pair(0))
And that works! Here's a screenshot to show the result:
Thanks, Thomas, for the suggestion about resetting the background after the paint!
The background character (which you have set with scr.bkgd) is a combination of video attribute, color pair and character which is merged with other characters added to the screen, e.g., via scr.addstr.
For what it's worth, X/Open Curses documents the feature in Rendition of Characters Placed into a Window.
The alternate character set aspect is one of those video attributes, and as documented by X/Open Curses:
the attributes specified, OR-ed with the window attributes.
If you don't want that, you can
temporarily set the background, erase the window (filling the background) and reset the background without the alternate character set, e.g.,
scr.bkgd(curses.ACS_NORMAL, curses.color_pair(1))
use a different method for adding characters to the screen. The underlying curses library waddchstr passes the video attributes directly (no merging). But it does not appear to be part of the Python binding (nothing similar in the reference manual). The attr parameter of addstr likely refers to the window attribute (set with a similar function (in X/Open curses, the "window colour").
Given the available functions (and limitations of the binding), calls with scr.bkgd are the way to solve the problem.
Related
I tried searching everywhere on the internet, but nowhere did I find an answer that worked for me, so I'm asking a new question.
In my code, I'm telling curses to get the terminal size and update some variables according to it. On my first try, I did something like this (this is the function that gets called after the window has been resized manually):
def resize():
rows, cols = stdscr.getmaxyx()
#some more code irrelevant to the question
When I found out that doesn't work, I realised that the stdscr is probably not getting resized, even though the terminal is. So I tried closing the stdscr and initialising it again:
def resize():
curses.endwin()
curses.wrapper(initialise)
#some more code that's irrelevant to the question
#showing the initialise function just in case:
def initialise(stdscrarg):
global stdscr
stdscr = stdscrarg
That, however, also didn't work. In other words, the stdscr initialised in the size that the terminal had before resizing. i.e. if I had a terminal over a quarter of my screen and then resized it to full screen, the function would correctly deal with the warping of the text, but it would redraw the content adjusted to just the original quarter of the screen, and would leave the junk characters in the rest of the screen, like this:
Before resizing
After resizing, before refreshing
After refreshing.
As you can see, the stdscr has initialised to its original size instead of taking on the size of the terminal. And I have tested it and confirmed that it really is the size of the stdscr, and not just the text printed on it (as when I gradually add strings to it, it throws an error when it reaches the end of the original size screen, instead of continuing to the end of the terminal screen and only then throwing an error.)
My question is: How can I get the new size of the terminal and make stdscr initialise with this new size?
Working on Windows 11, Python 3.10, module curses (though when installing it through pip, its name is windows-curses)
I am using a xfce4 terminal and I want to be able to detect if the background color is set to either black or white (or presumably some other color)
My code looks like this:
def print_color(string, style, textColor, background):
string = "\033[{};{};{}m{}\033[m ".format(style,textColor,background,string)
print(string)
I would like to detect the current background color and use it instead of passing it in.
I've tried not setting it, like this:
def print_color(string, style, textColor):
string = "\033[{};{};m{}\033[m ".format(style,textColor,string)
print(string)
but that did not work as I expected.
XFCE4 terminal uses VTE, which lacks the ability to respond to queries of the colors. That would be the SGR flavor of DECRQSS, which is mostly unimplemented in VTE.
(The example shown wouldn't work anyway). This is unrelated to the GTK+ toolkit.
I've searched around on the Internet and couldn't seem to find a way to remove the image I placed on a button. I was wondering if there is a way to remove the image but keep the button or any other simple quick fix. Here's some of my code for reference.
def breakcup():
if firstroom.cupnotbroken:
messagebutton.config(text="You broke the cup, and the key was inside the cup.")
cup.config(image=photo4)
firstroom.cupnotbroken=False
else:
cup.config(image=None, state=DISABLED)
messagebutton.config(text="You picked up the key")
firstroom.keynotfound=False
Obviously, image=None does not work, but it was the closest thing I could find as a solution.
root = Toplevel(bob)
root.geometry("640x360+200+250")
root.resizable(0, 0)
app = Room1(root)
The windows are made using the Toplevel(parent) function. Just to clarify.
This appears to be a bug with Tkinter. From my experimentation it seems safe to set the image to an empty string rather than None:
messagebutton.configure(image="")
This works because in the underlying tcl/tk interpreter "everything is a string". That is, the tcl equivalent to None is "". When you specify an empty string, Tkinter passes that empty string to tcl, and tcl interprets it as "no image".
The following code is being looped - is in a loop - but when 'inputStr' changes, the display does not. Printing inputStr yields the expected results, though.
defFnt = pygame.font.Font("CP437.ttf", 72)
txtToRndr = defFnt.render(inputStr,False, (0,0,0))
disp.blit(txtToRndr, (100,300))
Download link; http://www.mediafire.com/download/a4hp9wgojxgiao9/functGroup.rar
If you print inputStr right before its rendered it prints for a bit then stops, meaning it isnt getting rendered after a certain point, Which i think is because this condition:
if (16-len(Gnots))>0:
it must be coming out false therefore the code to render the new text isnt being executed:
if you print Gnots after the condition, it prints it until its length is 16 items than stops
change the number 16 in the condition to say 1000 as a test than try typing and the text changes
Your code needs refactoring. As the other answer says, the main problem is that if-block (try changing it to if True:.
I would recommend capping the framerate but drawing every frame unconditionally, as this is simpler and more robust. You're also not clearing the screen each frame, and PyGame has nice key tokens (e.g. pygame.K_ESCAPE) which you should use instead of numbers. You're also loading the font each time you draw; you only need to do so once, at the top of your program.
Here's my PyGame basecode, which shows some of these best practices. In the draw() function, you'd add your fill call to clear the screen, and then all of your rendering code.
I can suggest the following after encountering similar issue.
Try updating the screen with your text by adding following line after your code:
pygame.display.update()
The issue of text not updating on screen was coming in my case as I was trying to take input from terminal and then updating in on pygame screen.
Im trying to display a grid with moving individuals within it. At the moment im using a "clear screen" then display the grid. This is messy as the screen "flickers" every time.
In C and VB.NET there was methods of forcing the carriage to go back to the start of the console and overwrite content. This removed the flicker.
Is it possible in Python to do this? I've Googled around, and i found Curses, but thats Unix only (and i'll be working primarily within Windows).
Current Grid code (super basic):
#Clear() is a OS indepedent method of clearing the screen defined in code above, in windows its just os.system('cls')
clear()
x=0
y=0
tiles=""
tile=""
# Generate grid
while(y<max_y):
while(x<max_x):
tile = tileGen(x,y)
tiles += str(tile)
x+=1
tiles += "\n"
y+=1
x=0
print(tiles)
Maybe this will help: ANSI Escape Sequences
The Home command would be '\x1b[0;0H'.
For what it's worth, a python package does exist that wraps PDCurses, a windows-compatible curses library. The package, UniCurses, provides a uniform interface to either PDCurses (under windows) or python's native curses module, and so can be used to write cross-platform curses apps. It may be that Mike Desimone's answer is enough for your needs though.