Frage

In meinem Python-Skript, das Flüche verwendet, habe ich eine subwin zu denen einige Text zugeordnet ist. Da die Textlänge länger sein kann als die Fenstergröße sollte der Text scrollbaren sein.

Es scheint nicht, dass es irgendein CSS- „Überlauf“ wie Attribut für Flüche Fenster. Die Python / Curses docs sind auch eher kryptisch auf diesen Aspekt.

Hat jemand hier eine Idee, wie ich eine scrollbare Flüche Python-Code kann Subwindow mit und tatsächlich blättern durch das?

\ edit: präzisere Frage

War es hilfreich?

Lösung

OK mit window.scroll es war zu kompliziert, den Inhalt des Fensters zu bewegen. Stattdessen curses.newpad es für mich getan hat.

Erstellen Sie eine Unterlage:

mypad = curses.newpad(40,60)
mypad_pos = 0
mypad.refresh(mypad_pos, 0, 5, 5, 10, 60)

Dann können Sie blättern durch Erhöhen / Vermindern mypad_pos in Abhängigkeit von der Eingabe von window.getch () in cmd:

if  cmd == curses.KEY_DOWN:
    mypad_pos += 1
    mypad.refresh(mypad_pos, 0, 5, 5, 10, 60)
elif cmd == curses.KEY_UP:
    mypad_pos -= 1
    mypad.refresh(mypad_pos, 0, 5, 5, 10, 60)

Andere Tipps

Richtig, ich war ein wenig verwirrt, wie Pads zu verwenden (um Scroll-Text), und konnte es immer noch nicht herausfinden, nach dem Lesen dieser Nachricht; zumal ich wollte es in einem Kontext des Inhalts verwenden, um eine bestehende „Anordnung von Linien“ zu sein. Also habe ich ein kleines Beispiel vorbereitet, das zeigt Ähnlichkeiten (und Unterschiede) zwischen newpad und subpad:

#!/usr/bin/env python2.7
import curses

# content - array of lines (list)
mylines = ["Line {0} ".format(id)*3 for id in range(1,11)]

import pprint
pprint.pprint(mylines)

def main(stdscr):
  hlines = begin_y = begin_x = 5 ; wcols = 10
  # calculate total content size
  padhlines = len(mylines)
  padwcols = 0
  for line in mylines:
    if len(line) > padwcols: padwcols = len(line)
  padhlines += 2 ; padwcols += 2 # allow border
  stdscr.addstr("padhlines "+str(padhlines)+" padwcols "+str(padwcols)+"; ")
  # both newpad and subpad are <class '_curses.curses window'>:
  mypadn = curses.newpad(padhlines, padwcols)
  mypads = stdscr.subpad(padhlines, padwcols, begin_y, begin_x+padwcols+4)
  stdscr.addstr(str(type(mypadn))+" "+str(type(mypads)) + "\n")
  mypadn.scrollok(1)
  mypadn.idlok(1)
  mypads.scrollok(1)
  mypads.idlok(1)
  mypadn.border(0) # first ...
  mypads.border(0) # ... border
  for line in mylines:
    mypadn.addstr(padhlines-1,1, line)
    mypadn.scroll(1)
    mypads.addstr(padhlines-1,1, line)
    mypads.scroll(1)
  mypadn.border(0) # second ...
  mypads.border(0) # ... border
  # refresh parent first, to render the texts on top
  #~ stdscr.refresh()
  # refresh the pads next
  mypadn.refresh(0,0, begin_y,begin_x, begin_y+hlines, begin_x+padwcols)
  mypads.refresh()
  mypads.touchwin()
  mypadn.touchwin()
  stdscr.touchwin() # no real effect here
  #stdscr.refresh() # not here! overwrites newpad!
  mypadn.getch()
  # even THIS command erases newpad!
  # (unless stdscr.refresh() previously):
  stdscr.getch()

curses.wrapper(main)

Wenn Sie dies ausführen, zunächst werden Sie so etwas wie erhalten (newpad links, subpad rechts):

 ┌────────────────────────┐    ┌────────────────────────┐
 │Line 1 Line 1 Line 1 ───│    │Line 1 Line 1 Line 1 ───│
 │Line 2 Line 2 Line 2    │    │Line 2 Line 2 Line 2    │
 │Line 3 Line 3 Line 3    │    │Line 3 Line 3 Line 3    │
 │Line 4 Line 4 Line 4    │    │Line 4 Line 4 Line 4    │
 │Line 5 Line 5 Line 5    │    │Line 5 Line 5 Line 5    │
                               │Line 6 Line 6 Line 6    │
                               │Line 7 Line 7 Line 7    │
                               │Line 8 Line 8 Line 8    │
                               │Line 9 Line 9 Line 9    │
                               │Line 10 Line 10 Line 10 │
                               └────────────────────────┘

Einige Anmerkungen:

  • Sowohl newpad und subpad sollten ihre Breite / Höhe auf den Inhalt so bemessen (num Linien / max Linienbreite der Anordnung von Linien) + schließlichen Grenzraum
  • In beiden Fällen können Sie zusätzliche Linien mit scrollok() erlauben - aber nicht zusätzliche Breite
  • In beiden Fällen Sie im Grunde „Push“ eine Linie am unteren Rand des Kissens; und dann scroll() bis zu machen Platz für die nächste
  • Die spezielle refresh Methode, dass newpad hat, kann dann nur für eine Region dieses „ganzen Inhalts“ auf dem Bildschirm angezeigt werden; subpad mehr weniger hat in der Größe gezeigt wird, wurde in instanziiert
  • Wenn Sie die Grenzen der Pads ziehen, bevor Inhalt Strings Zugabe - dann werden die Grenzen scrollen (die das ─── Stück am ...Line 1 ───│ Teil gezeigt ist).

Nützliche Links:

Stellen Sie die window.scrollok (True).

Dokumentation

Ich wollte ein Scrolling-Pad-Display Inhalt einiger großer Textdateien verwenden, aber dies auch nicht funktionieren, weil Texte Zeilenumbrüche haben können und es war ziemlich hart, wie viele Zeichen-Display, um herauszufinden, zu einer Zeit, die passen gute Anzahl von Spalten und Zeilen.

beschlossen Also ich zum ersten Split meiner Textdateien in Zeilen genau SPALTEN Zeichen mit Leerzeichen Klotzen, wenn Linien zu kurz waren. Dann Scrollen der Text werden einfacher.

Hier ist ein Beispielcode eine beliebige Textdatei angezeigt werden:

#!/usr/bin/python
# -*- coding: utf-8 -*-

import curses
import locale
import sys

def main(filename, filecontent, encoding="utf-8"):
    try:
        stdscr = curses.initscr()
        curses.noecho()
        curses.cbreak()
        curses.curs_set(0)
        stdscr.keypad(1)
        rows, columns = stdscr.getmaxyx()
        stdscr.border()
        bottom_menu = u"(↓) Next line | (↑) Previous line | (→) Next page | (←) Previous page | (q) Quit".encode(encoding).center(columns - 4)
        stdscr.addstr(rows - 1, 2, bottom_menu, curses.A_REVERSE)
        out = stdscr.subwin(rows - 2, columns - 2, 1, 1)
        out_rows, out_columns = out.getmaxyx()
        out_rows -= 1
        lines = map(lambda x: x + " " * (out_columns - len(x)), reduce(lambda x, y: x + y, [[x[i:i+out_columns] for i in xrange(0, len(x), out_columns)] for x in filecontent.expandtabs(4).splitlines()]))
        stdscr.refresh()
        line = 0
        while 1:
            top_menu = (u"Lines %d to %d of %d of %s" % (line + 1, min(len(lines), line + out_rows), len(lines), filename)).encode(encoding).center(columns - 4)
            stdscr.addstr(0, 2, top_menu, curses.A_REVERSE)
            out.addstr(0, 0, "".join(lines[line:line+out_rows]))
            stdscr.refresh()
            out.refresh()
            c = stdscr.getch()
            if c == ord("q"):
                break
            elif c == curses.KEY_DOWN:
                if len(lines) - line > out_rows:
                    line += 1
            elif c == curses.KEY_UP:
                if line > 0:
                    line -= 1
            elif c == curses.KEY_RIGHT:
                if len(lines) - line >= 2 * out_rows:
                    line += out_rows
            elif c == curses.KEY_LEFT:
                if line >= out_rows:
                    line -= out_rows
    finally:
        curses.nocbreak(); stdscr.keypad(0); curses.echo(); curses.curs_set(1)
        curses.endwin()

if __name__ == '__main__':
    locale.setlocale(locale.LC_ALL, '')
    encoding = locale.getpreferredencoding()
    try:
        filename = sys.argv[1]
    except:
        print "Usage: python %s FILENAME" % __file__
    else:
        try:
            with open(filename) as f:
                filecontent = f.read()
        except:
            print "Unable to open file %s" % filename
        else:
            main(filename, filecontent, encoding)

Der wichtigste Trick ist die Zeile:

lines = map(lambda x: x + " " * (out_columns - len(x)), reduce(lambda x, y: x + y, [[x[i:i+out_columns] for i in xrange(0, len(x), out_columns)] for x in filecontent.expandtabs(4).splitlines()]))

Als erstes Tabellierungen im Text in Leerzeichen umgewandelt wird, dann habe ich Teilungslinien () -Methode meinen Text in Array von Zeilen zu konvertieren. Aber einige Zeilen können länger als unsere SäULEN Nummer, so dass ich jede Zeile in Batzen SPALTEN Zeichen aufgeteilt und verwenden dann reduzieren Sie die resultierende Liste in einer Liste von Linien zu verwandeln. Schließlich habe ich verwendet, um jede Zeile Karte Pad mit Leerzeichen Hinter so dass seine Länge genau SPALTEN Zeichen.

Hope, das hilft.

Dies ist die Antwort auf diese Frage: Wie ein Scroll-Menü in machen Python-Flüche

Mit diesem Code können Sie ein wenig Scrollen Menü in einem Kasten aus einer Liste von Zeichenketten erstellen.
Sie können auch diesen Code verwenden, um die Liste von Zeichenketten aus einer SQLite-Abfrage oder aus einer CSV-Datei zu bekommen.
Um die maximale Anzahl der Zeilen des Menüs bearbeiten Sie gerade bearbeiten max_row haben.
Wenn Sie das Programm Eingabetaste drücken den ausgewählten Zeichenfolge-Wert und seine Position drucken.

from __future__ import division  #You don't need this in Python3
import curses
from math import *



screen = curses.initscr()
curses.noecho()
curses.cbreak()
curses.start_color()
screen.keypad( 1 )
curses.init_pair(1,curses.COLOR_BLACK, curses.COLOR_CYAN)
highlightText = curses.color_pair( 1 )
normalText = curses.A_NORMAL
screen.border( 0 )
curses.curs_set( 0 )
max_row = 10 #max number of rows
box = curses.newwin( max_row + 2, 64, 1, 1 )
box.box()


strings = [ "a", "b", "c", "d", "e", "f", "g", "h", "i", "l", "m", "n" ] #list of strings
row_num = len( strings )

pages = int( ceil( row_num / max_row ) )
position = 1
page = 1
for i in range( 1, max_row + 1 ):
    if row_num == 0:
        box.addstr( 1, 1, "There aren't strings", highlightText )
    else:
        if (i == position):
            box.addstr( i, 2, str( i ) + " - " + strings[ i - 1 ], highlightText )
        else:
            box.addstr( i, 2, str( i ) + " - " + strings[ i - 1 ], normalText )
        if i == row_num:
            break

screen.refresh()
box.refresh()

x = screen.getch()
while x != 27:
    if x == curses.KEY_DOWN:
        if page == 1:
            if position < i:
                position = position + 1
            else:
                if pages > 1:
                    page = page + 1
                    position = 1 + ( max_row * ( page - 1 ) )
        elif page == pages:
            if position < row_num:
                position = position + 1
        else:
            if position < max_row + ( max_row * ( page - 1 ) ):
                position = position + 1
            else:
                page = page + 1
                position = 1 + ( max_row * ( page - 1 ) )
    if x == curses.KEY_UP:
        if page == 1:
            if position > 1:
                position = position - 1
        else:
            if position > ( 1 + ( max_row * ( page - 1 ) ) ):
                position = position - 1
            else:
                page = page - 1
                position = max_row + ( max_row * ( page - 1 ) )
    if x == curses.KEY_LEFT:
        if page > 1:
            page = page - 1
            position = 1 + ( max_row * ( page - 1 ) )

    if x == curses.KEY_RIGHT:
        if page < pages:
            page = page + 1
            position = ( 1 + ( max_row * ( page - 1 ) ) )
    if x == ord( "\n" ) and row_num != 0:
        screen.erase()
        screen.border( 0 )
        screen.addstr( 14, 3, "YOU HAVE PRESSED '" + strings[ position - 1 ] + "' ON POSITION " + str( position ) )

    box.erase()
    screen.border( 0 )
    box.border( 0 )

    for i in range( 1 + ( max_row * ( page - 1 ) ), max_row + 1 + ( max_row * ( page - 1 ) ) ):
        if row_num == 0:
            box.addstr( 1, 1, "There aren't strings",  highlightText )
        else:
            if ( i + ( max_row * ( page - 1 ) ) == position + ( max_row * ( page - 1 ) ) ):
                box.addstr( i - ( max_row * ( page - 1 ) ), 2, str( i ) + " - " + strings[ i - 1 ], highlightText )
            else:
                box.addstr( i - ( max_row * ( page - 1 ) ), 2, str( i ) + " - " + strings[ i - 1 ], normalText )
            if i == row_num:
                break



    screen.refresh()
    box.refresh()
    x = screen.getch()

curses.endwin()
exit()
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top