Giter Club home page Giter Club logo

pytermtk's Introduction

Linux Usage Python pyTermTk_version Test Status pypi_version pypi_version

screenshot

(python Terminal Toolkit) is a Text-based user interface library (TUI) Evolved from the discontinued project pyCuT and inspired by a mix of Qt5,GTK, and tkinter api definition with a touch of personal interpretation

pyTermTk.Showcase.002.webm

Try the Sandbox straight from your browser

SandBox

Powered by Pyodide and xterm.js and CodeMirror5 and w2ui


Be inspired by the Tutorials and the Examples

Don't get bored by the Api Definitions

Smell deliciousness with the official pyTermTk tool for designing and building Text-based user interfaces (TUIs)

Unravel your inner artist with The Terminal ASCII Photoshop


pyTermTk is available on PyPI

pip3 install --upgrade pyTermTk

Quick Test/Try - no install required

Clone

git clone https://github.com/ceccopierangiolieugenio/pyTermTk.git
cd pyTermTk

Demos

# Press CTRL-C to exit (CTRL-Break on Windows)

# Showcase Demo
python3 demo/demo.py -f

# run the ttkDesigner
python3 -m ttkDesigner

# Text edit with "Pygments" highlight integrated
# it require pygments
#   pip install pygments
python3 tests/test.ui.018.TextEdit.Pygments.py README.md

Projects using pyTermTk

  • ttkDesigner - the official pyTermTk tool for designing and building Text-based user interfaces (TUIs)
  • the DumbPaintTool - The Terminal ASCII Photoshop
  • tlogg - A fast, advanced log explorer.
  • ttkode - TerminalToolKit (Studio) Code (editor)
  • pytest-fold - A Pytest plugin to make console output more manageable when there are multiple failed tests
  • pytest-tui - A Text User Interface (TUI) for Pytest, automatically launched after your test run is finished
  • breakoutRL - Breakout the Roguelike
  • 7drl-2024 - A Snake🐍 on a Plane✈️ - The Roguelike

Related Projects

  • Honourable mention

    • bpytop - Linux/OSX/FreeBSD resource monitor
      This was the base inspiration for my core library
  • Python

    • urwid - Console user interface library for Python
    • pyTermGUI - A simple yet powerful TUI framework for your Python (3.7+) applications
    • Textual - TUI (Text User Interface) framework for Python inspired by modern web development
    • Rich - Python library for rich text and beautiful formatting in the terminal
    • PyCuT - terminal graphic library loosely based on QT api (my previous failed attempt)
    • pyTooling.TerminalUI - A set of helpers to implement a text user interface (TUI) in a terminal.
  • Non Python

pytermtk's People

Contributors

ceccopierangiolieugenio avatar dehesselle avatar eugenioparodisky2 avatar luchr avatar mgomersbach avatar nat-chan avatar schwehr avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

pytermtk's Issues

Discussion: Themes vs Styles vs LookAndFeel

This is not a bug-report or a report about a missing feature, but a "question/discussion" issue.

This question came up here

about the look and feel, I always wondered the possibility to allow some widgets to have a "style" attribute but I never formalised it.

Current state

I try to summarize the current state (please correct me, if/when my summary has errors):

  1. In TTkCfg there is an attribute theme which points to the "current" theme
  2. Widgets (e.g. a TTkFrame) check some theme-attributes at construction time (e.g. frameBorderColor, frameTitleColor)
  3. Widgets (e.g. a TTkFrame) check some theme-attributes at every call to paintEvent (e.g. TTkCfg.theme.grid)
  4. Widgets (e.g. a TTkFrame) support by keyword arguments to __init__ to not ask TTkCfg.theme for a color but to use the one explicitly given at construction time with an explicit keyword argument (e.g. titleColor=...)

Because of 3. it is possible to switch/change the grids, button-boxes, scrollbars, menubars, etc. dynamically (on the fly); which can be seen in the demo where one can switch from UTF-8 to ASCII theme.

Because of 2. a change in attributes like frameTitleColor has no effect on the widgets that are already constructed, but has an effect on every widget that is created after the theme-attribute(s) changed.

Because of 4. "many" slots are used (per widget) to save "their" colors (either the explicitly given ones from __init__ or the ones that were found in TTkCfg.theme by __init__).

[Some personal note: The asymmetry of 2. and 3. (getting some theme attributes at construction time and some at every paintEvent) is a little bit ... disturbing ... for me.]

Proposition/Suggestion

Here is an alternative approach which (in my opinion) simplifies things a bit:

Instead of the many color-slots (per widget) every widget hat only one look_and_feel (laf) slot. There a (reference to an) object is saved that is used at every paintEvent to ask the look_and_fool object for colors, grid-chars, borders-chars, etc. The default look_and_feel object is a "proxy" that "redirects" all the attribute-getters to the current TTkCfg.theme. All the widgets that use the default look_and_feel object see every change in TTkCfg.theme immediately (at the next repaint/update). But this scheme allows for other laf-objects: e.g. a look_and_feel-object that gives for some attributes (e.g. frameBorderColor ) some fixed colors that were chosen at the construction time of the laf-object and all the other attributes are proxied to TTkCfg.theme.

  1. (laf-resolution at paintEvent) So one can have laf-objects that (per default) proxy their attribute requests to TTkCfg.theme but have the ability to prescribe some attributes directly without asking TTkCfg.theme. So it's possible to use my_frame_laf = LookAndFeelProxy(); my_frame_laf.frameBorderColor = TTkColor.fg("#ff0000#"); as an laf-object for a frame that has (independent of the current theme) a red border, but all the other things (like the chars that are used for the border) are from the TTkCfg.theme.
  2. (colors, chars, etc. may depend on widget-state; method instead of pure values) Becasue laf-objects are objects (and not only stored color values) this allows for the ability to have methods in an laf-object that "computes" colors/chars taking the current state of the widget into account. This is the part that I used in the progressbar-WIP (often people want colors to depend on the "progress": one uses a progress bar to show how full something is and want to colorize the event, that this thing is nearly empty, below 10%, with some red color, etc.).
  3. (feel-parameters and feel-functions) But wait, there is more ... [in this commercial spot] :-) Why do I call this look_and_feel and not style? Let's make an example. Think of a PushButton (not a TTkButton) that can be pressed by a keyEvent (e.g. space or return) and shows it was pressed (via key) for some time and then goes automatically back in the unpressed state. This timing may be controlled by an attribute of an laf-object. So the keyEvent sets the pressed state and triggers an update and also starts a Timer to "unpress" the button in the near future. That's not a style or color but that is a "responsive" feeling.

Pros: less slots per widget; laf-object may "compute" the look-and-feel depending on the state of widget; more parameters possible (without using slots); no additional methods needed at the widgets to prescribe special look-and-feel (e.g. setBorderColor or the missing setTitleColor or setTitleAlign, etc.) for a widget.

Cons: one level of "indirection" (the "laf-Proxy") more at every paint-Event.

[Sorry for the long text.]

Suggestions for how to dynamically show/hide a text area when a line is clicked

Was wondering if you might have some suggestions on how to show/hide a text area (like TTkTextEdit widget) when a TTkList textClicked event occurs. I've managed to create a callback for a textClicked event which populates a TTkLogViewer widget, but ideally what I would like to be able to do is click the TTkList list element, and have a TextEdit widget pop up next to it (or under it) to show some text; and then when the list element is clicked again, to hide the TextEdit widget.

Basic idea like the third example movie here.

I hope this is clear what I am trying to do... :-)

[Question] table view can not scroll horizontally

Hello there,
These days, I'm using table view to show some information. There is one column coming with a very long str, and I have no idea how to make the horizontal scroll bar work. Would you please help to show me a demo about the table view with the horizontal scroll bar?
Great Thanks.

[Question]use mouse to select texts

Hello, great thanks for your efforts in this project. I have got a question as below.
Is there some way I can use to interrupt mouse monitoring so that I can select texts from the interface and do some copy action?
Thanks a lot.

Spinbox Input Error

So when manually putting a value in the SpinnerBox, it errors out and freezes everything.

Seems that manually typing a number explodes it.

    root.mainloop()
  File "/opt/virtualenvs/python3/lib/python3.8/site-packages/TermTk/TTkCore/ttk.py", line 154, in mainloop
    self._mainLoop()
  File "/opt/virtualenvs/python3/lib/python3.8/site-packages/TermTk/TTkCore/ttk.py", line 163, in _mainLoop
    self._input.start()
  File "/opt/virtualenvs/python3/lib/python3.8/site-packages/TermTk/TTkCore/TTkTerm/input.py", line 77, in start
    self.key_process(stdinRead)
  File "/opt/virtualenvs/python3/lib/python3.8/site-packages/TermTk/TTkCore/TTkTerm/input.py", line 161, in key_process
    self.inputEvent.emit(kevt, mevt)
  File "/opt/virtualenvs/python3/lib/python3.8/site-packages/TermTk/TTkCore/signal.py", line 124, in emit
    slot(*args, **kwargs)
  File "/opt/virtualenvs/python3/lib/python3.8/site-packages/TermTk/TTkCore/ttk.py", line 169, in _processInput
    self._key_event(kevt)
  File "/opt/virtualenvs/python3/lib/python3.8/site-packages/TermTk/TTkCore/ttk.py", line 229, in _key_event
    keyHandled = focusWidget.keyEvent(kevt)
  File "/opt/virtualenvs/python3/lib/python3.8/site-packages/TermTk/TTkWidgets/spinbox.py", line 84, in keyEvent
    return TTkLineEdit.keyEvent(self._lineEdit, evt)
  File "/opt/virtualenvs/python3/lib/python3.8/site-packages/TermTk/TTkWidgets/lineedit.py", line 236, in keyEvent
    self.textEdited.emit(self._text)
  File "/opt/virtualenvs/python3/lib/python3.8/site-packages/TermTk/TTkCore/signal.py", line 124, in emit
    slot(*args, **kwargs)
  File "/opt/virtualenvs/python3/lib/python3.8/site-packages/TermTk/TTkWidgets/spinbox.py", line 73, in _textEdited
    self.setValue(int(text))
TypeError: int() argument must be a string, a bytes-like object or a number, not 'TTkString'

Demo 'textedit.py' does not run

I get the following error when I try to run /demo/showcase/textedit.py:

$ python textedit.py
Traceback (most recent call last):
  File "/Users/jwr003/coding/pyTermTk/demo/showcase/textedit.py", line 69, in <module>
    main()
  File "/Users/jwr003/coding/pyTermTk/demo/showcase/textedit.py", line 65, in main
    demoTextEdit(rootTree)
  File "/Users/jwr003/coding/pyTermTk/demo/showcase/textedit.py", line 48, in demoTextEdit
    te.setReadOnly(False)
AttributeError: 'TTkTextEdit' object has no attribute 'setReadOnly'

I tried to fix the code by changing line 48 to te.isReadOnly = False, but then I got another error:

$ python textedit.py
Traceback (most recent call last):
  File "/Users/jwr003/coding/pyTermTk/demo/showcase/textedit.py", line 69, in <module>
    main()
  File "/Users/jwr003/coding/pyTermTk/demo/showcase/textedit.py", line 65, in main
    demoTextEdit(rootTree)
  File "/Users/jwr003/coding/pyTermTk/demo/showcase/textedit.py", line 49, in demoTextEdit
    te.setText(ttk.TTkString('\n').join([ getSentence(5,25,i) for i in range(50)]))
TypeError: TTkString.__init__() takes 1 positional argument but 2 were given

So it seems that the code might be broken in more than just one place...

How do I detect TTkTextEdit contents changed?

Hello, I am trying to detect if the user has change the contents of a TextEdit widget but I am having a hard time figuring it out.
Thank you again! I'll soon have something to show for all this effort.

self.te = ttk.TTkTextEdit(parent= (tef:=ttk.TTkFrame(parent=self.root,
						pos=(0,6),size=(42,7),border=True)),
						document=None,pos=(0,0),size=(41,5))
		self.te.setReadOnly(False)
		self.te.setLineWrapMode(ttk.TTkK.WidgetWidth)
		self.te.setWordWrapMode(ttk.TTkK.WordWrap)
		self.te.setText(self.lifepath.familyBackground)
		
		self.te.contentsChanged.connect(self.Unsaved) #here's where I fall flat.

`make doc` issues

I get the following error when attempting to make doc:

# Add "Signal" option in the method domains
sudo patch -d/ -p0  < ~/coding/PyTermTk/docs/sphynx.001.signal.patch
Password:
can't find file to patch at input line 3
Perhaps you used the wrong -p or --strip option?
The text leading up to this was:
--------------------------
|--- .venv/lib/python3.8/site-packages/sphinx/domains/python.py	2022-03-08 11:00:06.152347159 +0000
|+++ .venv/lib/python3.8/site-packages/sphinx/domains/python.py	2022-03-08 11:03:07.292940495 +0000
--------------------------
File to patch: 
sphynx.001.signal.patch: No such file or directory
Skip this patch? [y] 
Skipping patch.
2 out of 2 hunks ignored
make: *** [.venv] Error 1

I also get this if I try to issue make doc again after the failed attempt. I have to rm -rf .venv/ to get it to start building again.

# old doc gen, using pdoc3 ; \
	# . .venv/bin/activate ; \
	# rm -rf docs/html ; \
	# pdoc --html TermTk -o docs/html ; \
	. .venv/bin/activate ; \
	rm -rf docs/build ; \
	rm -rf docs/source/autogen.* ; \
	# sphinx-apidoc -o docs/source/TermTk/ -e TermTk/ ; \
	make -C docs/ clean ; \
	make -C docs/ html ; \
	cp -a docs/images docs/build/html/_images ;

One other small build issue:
Makefile creates a virtual environment in the .venv folder. This is likely to clash with pre-existing virtual environment folders. Please consider making the name something less common.

[Question] How to properly dispose a window and all its content

Hi,

Sorry if this a dumb question, but what is the best way to close properly a window and destroy all its content?

I've been searching for an example but I've not found anything...

I've tried to use .close() method from TTKWindow() class but not sure what I'm missing as it do not close window... only thing I'm able to do is hide and show window... but actually I wanted to destroy it... unless

Thanks

Change TTkCheckbox checked status

So there's a strange imbalance between bool and int values for Checkbox states.
I was trying to use bool to .setCheckState() and .setChecked() however only when I switched to using 0 and 2 (ignoring the half-state of 1) did I find some success.

Entire Form Wipe

Hello! Is there a limit to the number of characters available? I was making a dynamic frame that would get it's size based on the number of items I needed to put inside it but at some point, the whole form goes to away. I decided to shelve that and work on scroll bars but after extending the frame down, it did it again.

Any clue on why the screen partially or fully blanks?

image

Code Source
https://replit.com/@nickandwolf/NaturalBoldCopyrightinfringement?v=1

Spinbox widget breaks when I use backspace to delete all its contents

Hi thanks a lot for this fantastic project, I've been learning to use it, and I really like it.

Recently I hit below error when I using a SpinBox and want to correct the actual value myself and set manually.

Let's say spinbox, shows 500 as value and I wanted to set it to 1, or any other number, when you use back space key there, all is ok if you DO NOT delete all text(numbers) in there, when you delete last digit then this happens:

Traceback (most recent call last):
  File "/Users/larrycastro/Documents/workspace/lab-constructor/./lab-constructor.py", line 1960, in <module>
    tui_menu()
  File "/Users/larrycastro/Documents/workspace/lab-constructor/./lab-constructor.py", line 1884, in tui_menu
    rootWindow.mainloop()
  File "/usr/local/lib/python3.10/site-packages/TermTk/TTkCore/ttk.py", line 113, in mainloop
    self._mainLoop()
  File "/usr/local/lib/python3.10/site-packages/TermTk/TTkCore/ttk.py", line 122, in _mainLoop
    self._input.start()
  File "/usr/local/lib/python3.10/site-packages/TermTk/TTkCore/TTkTerm/input.py", line 77, in start
    self.key_process(stdinRead)
  File "/usr/local/lib/python3.10/site-packages/TermTk/TTkCore/TTkTerm/input.py", line 155, in key_process
    self.inputEvent.emit(kevt, mevt)
  File "/usr/local/lib/python3.10/site-packages/TermTk/TTkCore/signal.py", line 123, in emit
    slot(*args, **kwargs)
  File "/usr/local/lib/python3.10/site-packages/TermTk/TTkCore/ttk.py", line 128, in _processInput
    self._key_event(kevt)
  File "/usr/local/lib/python3.10/site-packages/TermTk/TTkCore/ttk.py", line 188, in _key_event
    keyHandled = focusWidget.keyEvent(kevt)
  File "/usr/local/lib/python3.10/site-packages/TermTk/TTkWidgets/spinbox.py", line 84, in keyEvent
    return TTkLineEdit.keyEvent(self._lineEdit, evt)
  File "/usr/local/lib/python3.10/site-packages/TermTk/TTkWidgets/lineedit.py", line 233, in keyEvent
    self.textEdited.emit(self._text)
  File "/usr/local/lib/python3.10/site-packages/TermTk/TTkCore/signal.py", line 123, in emit
    slot(*args, **kwargs)
  File "/usr/local/lib/python3.10/site-packages/TermTk/TTkWidgets/spinbox.py", line 73, in _textEdited
    self.setValue(int(text))
ValueError: invalid literal for int() with base 10: ''

I'm thinking to do a workaround at the valueChanged to catch all there and prevent this exception... not sure if this can work..,

I also think this is a bug, because I just tried on your online sandbox, and I think it breaks (https://ceccopierangiolieugenio.github.io/pyTermTk/sandbox/sandbox.html) widgets at spinxbox field example.

Please let me know if you need any ohter info from me.
Regards

TTkString object has no attribute 'split'

Hi,

It's fantastic, but I'd like to display simple text wrapping in a window. As long as I could find out, the texedit widget (in texedit.py) is for that (?).
But it has a problem. On the demo, clicking on Layouts | Sources gives the error in the subject. Even after correcting it, there is another error popping up.

Thanks,

Demo "filepicker.py" causes exception when button is clicked

I can run pyTermTk/demo/showcase/filepicker.py, but when I then click one of the left two buttons while the program is running, I get an exception, and the terminal output gets corrupted (and I must issue a reset in the terminal to use it again).

image

Cannot test TTkString against NoneType

self.firstName is variable that starts None and become a string later.
It is later assigned a value by a LineEdit.

if self.firstName == None:

  File "/opt/virtualenvs/python3/lib/python3.8/site-packages/TermTk/TTkCore/string.py", line 140, in __eq__
    def __eq__(self, other): return self._text == other if type(other) is str else self._text == other._text
AttributeError: 'NoneType' object has no attribute '_text'

[Question] General Question... Progress bar

Hi there,

Do you have any plans to implement a progress bar witget? I'm trying to build one , thinking on event/signal, I was also looking at your demo graph... Any advice?

Help with choosing appropriate widgets for project

Pytest-fold is a Pytest plugin that attempts to display results of a Pytest run in a way that is easier to visualize than Pytest's "dump it all to console" output. The idea is to display Pass/Fail (and maybe other) results on the console in a "folded" manner, where only the title is visible until it is clicked; at which time the full details of that test are "unfolded" onto the console for viewing. If that test is clicked again, it folds back up. You can get an idea of what I mean by looking at the 2nd and 3rd movies in the README. I have already implemented two simple versions of the clickable 'fold' feature - one in Asciimatics, and one in Textual. Now I am trying to do a TUI version in PyTermTk, and would like some advice on what widgets might be best for implementing this idea.

Basically, I need a widget that displays a line of text (the test titles), allows me to click on it, and then displays full test detail information. In the two movies I mentioned above, you can see two different ways I've done it - (a) a list of test titles stacked vertically that can be clicked, and which open/close in place; (b) a tree that lists test titles as nodes, and then displays the test details in a separate text box.

I already have a simple TUI built up in PyTermTk, in which the various output sections from Pytest are displayed in tabbed text boxes. Because I am not super-familiar with the Tk way of doing things, I thought I would ask an expert for a suggestion on how to do this. :-) Any ideas?

Connecting Spinbox to Evaluate it's own value

I don't know if it's my garbage python programming or what but I cannot make a SpinBox evaluate it's own .value()
Full thing can be found HERE

def BuildThing(self):
    self.currentMA = ttk.TTkSpinBox(parent=ttk.TTkFrame(parent=self.statFrame,
            border=True, pos=(2, 24), size=(6, 3)), value=self.character.GetCurrentMA(), #returns an integer
            pos=(0, 0), size=(4, 1)).valueChanged.connect(self.ChangeMA)

def ChangeMA(self, v=None):
    #some label I made elsewhere and updates unless I call self.currentMA.value()
    self.lift.setText(str(self.currentMA.value()))
    
    #File "/home/runner/NaturalBoldCopyrightinfringement/characters/character.py", line 241, in ChangeMA
    #self.lift.setText(str(self.currentMA.value()))
    #AttributeError: 'NoneType' object has no attribute 'value'

Force Window Focus

Hello! Is there a window.focus() command or something to force a window to be up front? Sometimes when I make a new window, an area 'behind' it takes the focus away.

Rendering ANSI-encoded text corrupts terminal output

Hello,

I'm working on a pyTermTk app that takes the terminal output from a Pytest run (which is ANSI-encoded text), and renders it inside a TTkTextEdit widget. It seems that every line that has ANSI codes in it results in some corruption of the rendered text on the screen.

Here is a stripped down source file to demonstrate what I mean. BTW I am running on a MacBook Pro, running in iTerm2.

import TermTk as ttk
from os import get_terminal_size

PYTEST_STATS = 8 * """�[31m================================================= �[31m�[1m7 failed�[0m, �[32m3 passed�[0m, �[33m1 skipped�[0m, �[33m1 xfailed�[0m, �[33m1 xpassed�[0m, �[31m�[1m2 errors�[0m�[31m in 0.93s�[0m�[31m =================================================�[0m"""

PYTEST_OUTPUT = 10 * """�[1m========================================================================== test session starts ===========================================================================�[0m
platform darwin -- Python 3.10.2, pytest-6.2.5, py-1.11.0, pluggy-1.0.0 -- /Users/jwr003/coding/pytest-fold/venv/bin/python
cachedir: .pytest_cache
metadata: {'Python': '3.10.2', 'Platform': 'macOS-12.2.1-x86_64-i386-64bit', 'Packages': {'pytest': '6.2.5', 'py': '1.11.0', 'pluggy': '1.0.0'}, 'Plugins': {'html': '3.1.1', 'metadata': '1.11.0', 'Faker': '13.0.0', 'fold': '0.7.4'}, 'JAVA_HOME': '/Users/jwr003/Library/Java/JavaVirtualMachines/corretto-11.0.12/Contents/Home'}
rootdir: /Users/jwr003/coding/pytest-fold, configfile: pytest.ini, testpaths: tests
plugins: html-3.1.1, metadata-1.11.0, Faker-13.0.0, fold-0.7.4
�[1mcollecting ... �[0m�[1m
collected 15 items                                                                                                                                                       �[0m

tests/test_pytest_fold.py::test_1_passes_and_has_lots_of_logging_output �[32mPASSED�[0m�[32m                                                                                     [  6%]�[0m
tests/test_pytest_fold.py::test_2_fails_and_has_lots_of_logging_output �[31mFAILED�[0m�[31m                                                                                      [ 13%]�[0m
tests/test_pytest_fold.py::test_3_fails �[31mFAILED�[0m�[31m                                                                                                                     [ 20%]�[0m
tests/test_pytest_fold.py::test_4_passes �[32mPASSED�[0m�[31m                                                                                                                    [ 26%]�[0m
tests/test_pytest_fold.py::test_5_marked_SKIP �[33mSKIPPED�[0m (unconditional skip)�[31m                                                                                         [ 33%]�[0m
tests/test_pytest_fold.py::test_6_marked_xfail_but_passes �[33mXPASS�[0m�[31m                                                                                                    [ 40%]�[0m
tests/test_pytest_fold.py::test_7_marked_xfail_and_fails �[33mXFAIL�[0m�[31m                                                                                                     [ 46%]�[0m
tests/test_pytest_fold.py::test_8_causes_a_warning �[31mFAILED�[0m�[31m                                                                                                          [ 53%]�[0m
tests/test_pytest_fold.py::test_8_5_lorem_fails �[31mFAILED�[0m�[31m                                                                                                             [ 60%]�[0m
tests/test_pytest_fold.py::test_9_fail_capturing �[31mFAILED�[0m�[31m                                                                                                            [ 66%]�[0m
tests/test_pytest_fold.py::test_10_pass_capturing �[31mFAILED�[0m�[31m                                                                                                           [ 73%]�[0m
tests/test_pytest_fold.py::test_11_fails_and_has_stdout �[31mFAILED�[0m�[31m                                                                                                     [ 80%]�[0m
tests/test_pytest_fold.py::test_12_passes_and_has_stdout �[32mPASSED�[0m�[31m                                                                                                    [ 86%]�[0m
tests/test_pytest_fold.py::test_13_causes_error_pass_stderr_stdout_stdlog �[31mERROR�[0m�[31m                                                                                    [ 93%]�[0m
tests/test_pytest_fold.py::test_14_causes_error_fail_stderr_stdout_stdlog �[31mERROR�[0m�[31m                                                                                    [100%]\n\n�"""


def main():
    root = ttk.TTk()
    term_size = get_terminal_size()

    main_window = ttk.TTkWindow(
        parent=root,
        pos=(0, 0),
        size=(term_size.columns, term_size.lines),
        title=PYTEST_STATS,
        border=True,
    )
    main_layout = ttk.TTkHBoxLayout()
    main_window.setLayout(main_layout)

    tab_widget = ttk.TTkTabWidget(parent=main_window)

    text_edit = ttk.TTkTextEdit(parent=tab_widget)
    text_edit.setText(PYTEST_OUTPUT)
    tab_widget.addTab(text_edit, "Pytest Results")

    root.mainloop()


if __name__ == "__main__":
    main()

Clicking a Disabled Button resend previous signal

I have a button setup and if we're at Step 1, then <PREV needs to be disabled. Once disabled, I clicked on it and it repeated the last function. So if that was the NEXT> connected function, it ran that. If it was a popup window button, it would pop up more windows.

Very interesting bug 😄

String len() is used as width

Description of the problem

Looking at the code I see many lines where the len() of a string is used for the (terminal-)width of this string. But there are codepoints with width 0 and 2. For example "o" with an arrow above: o⃗ (U+006F U+20D7). The U+20D7 arrow has width 0. Or 😼 (U+1f63c): this codepoint has width 2. If one enters or uses such codepoints the whole layout is "out of sync".

Example

Here is an example with demo.py and the form widgets: Before:
20221122_210446
and after:
20221122_210526

Question

Are there any plans to support wcwidth?

Right way to quit app

Good day.
I am trying to exit the application using the TTkHelper.quit() command - the program closes, but after that the pressed buttons are not displayed in the console.
This is bug or exist right way to do that?

Integration with a TK Designer?

Hello, first off, let me say, thanks for creating this project - it is very cool and looks very promising!

I am not particularly familiar with Tk design, so using something like Tk Designer is attractive to me. Is there any way it would work with pyTermTk? Forgive the n00b question. :-)

(p.s. I am evaluating pyTermTk's use for one of my own projects)

Button text does not appear until clicked

Hello,

I have a button that is connected to a Quit method. When initially rendered, the "Quit" text does not show. In fact it only shows when you click the button, at which time the "Quit" text appears. Then, when clicked a second time, the application quits.

Here is a movie showing the problem:
https://user-images.githubusercontent.com/4308435/160181478-647b757c-b437-42f2-a645-8ff443e5e9a5.mov

I get this same behavior on Mac using either iTerm2 or the built in Terminal application.

Any ideas what is wrong? Here is a code snippet:

    root = ttk.TTk()

    # Create main window
    top_frame = ttk.TTkFrame(
        parent=root,
        pos=(0, 0),
        size=(TERMINAL_SIZE.columns - 10, 3),
        border=True,
    )
    top_label = ttk.TTkLabel(
        parent=top_frame, pos=(0, 0)  # , size=(TERMINAL_SIZE.columns - 10, 3)
    )
    top_label.setText(ttk.TTkString(summary_results))
    # top_label.setText(summary_results)

    # Create Quit button
    button_frame = ttk.TTkFrame(
        parent=root,
        pos=(TERMINAL_SIZE.columns - 10, 0),
        size=(10, 3),
        border=True,
        layout=ttk.TTkVBoxLayout(),
    )
    quit_button = ttk.TTkButton(parent=button_frame, text="Quit")
    quit_button.layout()
    quit_button.clicked.connect(quit)

Exception when connecting signal to slot

OK, what am I doing wrong here? I get en exception when this code runs and the results_list.textClicked.connect method is called. I believe my slot and signal APIs match (no parameters).

    @ttk.pyTTkSlot()
    def _results_list_callback() -> None:
        test_text = "Hi"

    def create_result_lists(self) -> None:
        for result in ("Errors", "Passes", "Failures", "Skipped", "Xfails", "Xpasses"):
            results_list = ttk.TTkList(
                parent=self.tab_widget,
                selectionMode=ttk.TTkK.MultiSelection,
            )

            results_list.textClicked.connect(self._results_list_callback)

            for key in eval(f"self.test_results.{result.lower()}.keys()"):
                results_list.addItem(key)

            self.tab_widget.addTab(results_list, f" {result} ")

Traceback:
Screen Shot 2022-03-27 at 9 06 13 AM

Scrollbars

Hello again! I am trying to tie a scrollbar to a frame but cannot seem to find clear examples or documentation. I just need a vertical bar.

Thank you!

focusIn focusOut signals

So I'm new to this "team coding" thing and have don't have the experience (yet) to help add the features I'd like to see but how about some Focus Signals?

My use case is when focusing in on a Spinbox, it changes a label's text to explain what that Spinbox does in more detail. I'm going to try overloading the Spinbox Class but later on, I would love to help add that kind of stuff. I just need to learn a bit more before then.

I haven't tested this yet...

class TTkSpinBox(TTkWidget):
    '''TTkSpinBox'''
    __slots__= (
        '_lineEdit', '_value', '_maximum', '_minimum',
        '_mouseDelta', '_valueDelta', '_draggable',
        # Signals
        'valueChanged','focusIn','focusOut')
    def __init__(self, *args, **kwargs):
        # Signals
        self.valueChanged=pyTTkSignal(int)
        self.focusIn=pyTTkSignal(str)
        self.focusOut=pyTTkSignal(str)

    def focusInEvent(self):
        self._lineEdit._color = TTkCfg.theme.lineEditTextColorFocus
        self._lineEdit.update()
        self.valueChanged.emit(self.__name__)

    def focusOutEvent(self):
        self._draggable = False
        self._lineEdit._color = TTkCfg.theme.lineEditTextColor
        self._lineEdit.focusOutEvent()
        self._lineEdit.update()
        self.valueChanged.emit(self.__name__)

Demo "demo.py" does not run

$ python /Users/jwr003/coding/pyTermTk/demo/demo.py
Traceback (most recent call last):
  File "/Users/jwr003/coding/pyTermTk/demo/demo.py", line 246, in <module>
    main()
  File "/Users/jwr003/coding/pyTermTk/demo/demo.py", line 241, in main
    demoShowcase(winTabbed1, border)
  File "/Users/jwr003/coding/pyTermTk/demo/demo.py", line 154, in demoShowcase
    tabWidgets.addTab(demoTextEdit(),    " Text Edit ")
  File "/Users/jwr003/coding/pyTermTk/demo/showcase/textedit.py", line 49, in demoTextEdit
    te.setText(ttk.TTkString('\n').join([ getSentence(5,25,i) for i in range(50)]))
TypeError: TTkString.__init__() takes 1 positional argument but 2 were given

ListBox Get Selected Item

I have no clue on how to get a selected item or default the List to specific choice.
I've resorted to using:

self.lw.items()[0].selected = True
self.lw.items()[0].highlighted = True

for ensuring the first item is highlighted. And I'm cycling through the list to check what current choice is selected.

For context, the List is used to select objects to edit. I am trying to create a Save function which is checks what step the user is on and then pulls the widgets' current values and assigns them to the right variables.

When trying selectedItems() or selectedLabels() both come up empty ( [] )

Only for unix?

This isn't listed anywhere in the limitations but is this project meant only for unix systems? Windows immediately produces the following error in Windows Terminal:

ERROR: No module named 'termios'

[Question] React to sub-menubar event/signal

Hi there, I'm sorry to bother, but I just can't figure out how to handle event/signals from submenu's. I tried something like

def menu_pressed(button):
    ttk.TTkLog.debug(f"menu_pressed: {button.text}")

menu = frameTop.menubarTop().addMenu("Menu Button")

submenu = menu.addMenu("Category 1")
submenu.addMenu("New").menuButtonClicked.connect(menu_pressed)

other_submenu = menu.addMenu("Category 2")
other_submenu.addMenu("New").menuButtonClicked.connect(menu_pressed)

But now I can not distinguish between them since the emited button.text is in both cases "New". I also cannot use a different callback function since the menu is suppossed to be generated on runtime.

I really like this library and really appreciate any help.

Thanks a lot!

Passing int(LineEdit.text())

Ran into an issue trying to set a SpinBox's value with a LineEdit.
using v._text works though
strange because your code for LineEdit has:

def text(self):
        '''text'''
        return self._text

Here's my thing:

#HumanityChanged is called by a LineEdit
#currentEmp and emp are SpinBoxes
#GetCurrentEMP returns an integer after doing hokey math on the arguments
def HumanityChanged(self, v=-1):
    self.currentEmp.setValue(self.character.GetCurrentEMP(int(v.text()), self.emp.value()))
    #AttributeError: 'TTkString' object has no attribute 'text'

How to debug with intellij idea?

Good afternoon. Your work is very interesting.
I'm trying to launch a debag in a similar way:

import pydevd_pycharm
    
pydevd_pycharm.settrace('192.168.56.1', port=38600, stdoutToServer=False, stderrToServer=False, suspend=False)

As a result, the image is displayed, but there is no response to the actions.

I would venture to assume that it's about transferring input to the debugging server, but in the example it is turned off and there is still no response.

In the case without a debug, it works fine.

Here is full code:

#!/usr/bin/env python3
from TermTk import TTkVBoxLayout, TTkButton, TTk

def main():
    import pydevd_pycharm
    pydevd_pycharm.settrace('192.168.56.1', port=38600,
                            stdoutToServer=False, stderrToServer=False, suspend=False)

    root = TTk()

    view = TTkVBoxLayout()
    root.setLayout(view)
    button = TTkButton(border=True, text="Button1")
    view.addWidget(button)
    button.clicked.connect(lambda: print('test'))

    root.mainloop()

if __name__ == "__main__":
    main()

demo/gittk.py doesn't work (but I fixed it)

This demo (python gittk.py) doesn't run correctly due to two errors:

  1. The call to git.Repo is made with . as its argument, so if you are in a subdirectory of the repo (like, in the /demo folder), it fails. Fix is to add search_parent_directories to Line 38:

repo = git.Repo('.', search_parent_directories=True)

  1. Line 97 has syntax errors, and should be:

diffText.setText(line)

AFter making those changes, it seems to work.

Close Window Button

Hello again! I managed to make a little X button on a window but I do not know how to call the window close function when the X is clicked. I can make the X go away but not the window itself.

Windows with Frame

Hello! For the life of me, I cannot get frames to render in a window.

Duplicated button

Forgive me for being a total Tk n00b, but what am I doing wrong? I have a pyTermTk app that displays the results from Pytest runs. At the top of the app is a TkFrame that displays the overall test run statistics. And next to it is a button ("Quit") that exits the program when clicked.

A couple of things are wrong:

  • The Quit button is duplicated when the app is rendered
  • At first only the duplicate shows up (in the top-left TkFrame, but is not clickable); although the TkFrame that holds the actual Quit button is rendered (upper right), you just can't see the Quit label
  • "Quit" text shows up once the actual button (upper-right) is clicked; and then when clicked a second time, actually quits the app

Here is the code.

Pressing Ctrl-Z while script is running causes exception

An AttributeError occurs when I press Ctrl-Z in any of the scripts I run. line 112 of term.py isattempting to access a non-existing echo attribute in the TTkTerm class.

For example, while running pyTermTk/demo/showcase/windows.py:

$ python windows.py
Traceback (most recent call last):
  File "/Users/jwr003/coding/pyTermTk/demo/showcase/windows.py", line 57, in <module>
    main()
  File "/Users/jwr003/coding/pyTermTk/demo/showcase/windows.py", line 54, in main
    root.mainloop()
  File "/Users/jwr003/coding/pyTermTk/venv/lib/python3.10/site-packages/TermTk/TTkCore/ttk.py", line 115, in mainloop
    evt = self.events.get()
  File "/Users/jwr003/.pyenv/versions/3.10.2/lib/python3.10/queue.py", line 171, in get
    self.not_empty.wait()
  File "/Users/jwr003/.pyenv/versions/3.10.2/lib/python3.10/threading.py", line 320, in wait
    waiter.acquire()
  File "/Users/jwr003/coding/pyTermTk/venv/lib/python3.10/site-packages/TermTk/TTkCore/ttk.py", line 208, in _SIGSTOP
    TTkTerm.stop()
  File "/Users/jwr003/coding/pyTermTk/venv/lib/python3.10/site-packages/TermTk/TTkCore/TTkTerm/term.py", line 112, in stop
    TTkTerm.echo(True)
AttributeError: type object 'TTkTerm' has no attribute 'echo'

[Question] Paste text contents into LineEdit does not perform well

When I tried to paste something into widget Line Edit using [ctrl] + [insert], the widget didnot show all the contents.
I digged into this situation and find that it is possibly because of this file [TermTk/TTkCore/TTkTerm/readinputlinux.py].
I tried to fix this problem by changing some of the code as below:

`

class ReadInput():
    __slots__ = ('_readPipe','_attr', '_closeFlag')

    def __init__(self):
        self._readPipe = os.pipe()
        self._attr = termios.tcgetattr(sys.stdin)
        tty.setcbreak(sys.stdin)
        self._closeFlag = False

    def close(self):
        termios.tcsetattr(sys.stdin, termios.TCSANOW, self._attr)
        # os.write(self._readPipe[1], b'quit')
        os.write(self._readPipe[1], b'quit')
        self._closeFlag = True

    def cont(self):
        tty.setcbreak(sys.stdin)

    def read(self):

        while sys.stdin.readable() and self._closeFlag == False:
            stdinRead = sys.stdin.read(1)
            if self._closeFlag == True:
                break

            if stdinRead == "\033":
                _fl = fcntl.fcntl(sys.stdin, fcntl.F_GETFL)
                fcntl.fcntl(sys.stdin, fcntl.F_SETFL, _fl | os.O_NONBLOCK) # Set the input as NONBLOCK to read the full sequence
                stdinRead += sys.stdin.read(20)       # Check if the stream start with an escape sequence
                if stdinRead.startswith("\033[<"):    # Clear the buffer if this is a mouse code
                    sys.stdin.read(0x40)
                fcntl.fcntl(sys.stdin, fcntl.F_SETFL, _fl)
           
            return stdinRead

`
Hope that will work.

Escape Commands in Titles

Hah, so I was getting stupid and put /r and /n as escape commands to see if I could stack a title but it just destroys the whole line across the terminal.

title="New Line"
image

title="New\nLine"
image

title="New\rLine"
image

title="New\tLine"
image

title="New\bLine"
image

title="New\fLine"
image

This isn't really a serious bug or anything, just something I noticed. Very low priority.

Request: text wrap feature

I can't find anything in the source or the docs that discusses text wrapping if text is wider than the widget on which it is displayed. I would like to have this option, if possible. And it would be even better if he user could specify the wrap column number, in case they want to wrap at a different boundary than the widget width. Thank you for your consideration!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.