سؤال

في البرنامج النصي Python الذي يستخدم اللعنات ، لديّ Subwin تم تعيين بعض النص عليه. نظرًا لأن طول النص قد يكون أطول من حجم النافذة ، يجب تمرير النص.

لا يبدو أن هناك أي CSS- "فائض" مثل السمة لنوافذ اللعنات. مستندات Python/Curses هي أيضا خفية إلى حد ما على هذا الجانب.

هل لدى أي شخص هنا فكرة كيف يمكنني ترميز الريف الفرعي لعنات قابلة للتمرير باستخدام Python والتمرير من خلاله فعليًا؟

تحرير: سؤال أكثر دقة

هل كانت مفيدة؟

المحلول

حسنًا مع Window.Scroll كان الأمر معقدًا للغاية لتحريك محتوى النافذة. بدلاً من ذلك ، فعلت Curses.newpad ذلك بالنسبة لي.

إنشاء لوحة:

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

ثم يمكنك التمرير عن طريق زيادة/تقليل mypad_pos اعتمادًا على المدخلات من window.getch () في 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)

نصائح أخرى

حسنًا ، كنت مرتبكًا بعض الشيء حول كيفية استخدام الفوط (من أجل التمرير النص) ، وما زلت لا أستطيع اكتشافه بعد قراءة هذا المنشور ؛ خاصة وأنني أردت استخدامه في سياق المحتوى كونه "مجموعة من الخطوط" الحالية. لذلك قمت بإعداد مثال صغير ، يظهر أوجه التشابه (والاختلافات) بين newpad و 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)

عندما تقوم بتشغيل هذا ، ستحصل في البداية على شيء مثل (newpad اليسار، subpad حق):

 ┌────────────────────────┐    ┌────────────────────────┐
 │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 │
                               └────────────────────────┘

بعض الملاحظات:

  • كلاهما newpad و subpad يجب أن يكون لها عرض/ارتفاع بحجم المحتوى (خطوط NUM/عرض خط الحد الأقصى لمجموعة الخطوط) + مساحة الحدود النهائية
  • في كلتا الحالتين ، يمكنك السماح بخطوط إضافية مع scrollok() - ولكن ليس عرض إضافي
  • في كلتا الحالتين ، يمكنك "دفع" خطًا في أسفل اللوحة ؛ وثم scroll() حتى إفساح المجال لآخر
  • الخاص refresh طريقة ذلك newpad بعد ذلك ، يسمح فقط بإظهار منطقة من "المحتوى الكامل" على الشاشة ؛ subpad لا بد من إظهار أقل في الحجم الذي تم إنشاءه فيه
  • إذا رسمت حدود الفوط قبل إضافة سلاسل المحتوى - فإن الحدود سوف تنتقل أيضًا (هذا هو ─── قطعة مبينة في ...Line 1 ───│ جزء).

روابط مفيدة:

اضبط window.scrollok (صواب).

توثيق

كنت أرغب في استخدام لوحة التمرير لعرض محتوى بعض الملفات النصية الكبيرة ، لكن هذا لم ينجح بشكل جيد لأن النصوص يمكن أن تحتوي على فترات فواصل بين الأسطر وكان من الصعب جدًا معرفة عدد الأحرف التي يجب عرضها في وقت واحد لتناسب العدد الجيد من الأعمدة والصفوف.

لذلك قررت أولاً تقسيم ملفاتي النصية في خطوط أحرف الأعمدة بالضبط ، قم بالتحريض مع المساحات عندما كانت الخطوط قصيرة جدًا. ثم يصبح التمرير النص أكثر سهولة.

فيما يلي نموذج رمز لعرض أي ملف نصي:

#!/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)

الحيلة الرئيسية هي الخط:

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()]))

أولاً ، يتم تحويل الجداول في النص إلى مسافات ، ثم استخدمت طريقة splitlines () لتحويل نصي في مجموعة من الخطوط. ولكن قد تكون بعض الخطوط أطول من رقم الأعمدة لدينا ، لذلك قمت بتقسيم كل سطر في أحرف من أعمدة الأعمدة ثم استخدمت تقليلها لتحويل القائمة الناتجة في قائمة الخطوط. أخيرًا ، استخدمت MAP لتسخين كل سطر مع مساحات زائدة بحيث يكون طوله أحرف أعمدة بالضبط.

أتمنى أن يساعدك هذا.

هذا هو إجابة هذا السؤال:كيفية صنع قائمة التمرير في بيثون كورس

يتيح لك هذا الرمز إنشاء قائمة تمرير صغيرة في مربع من قائمة الأوتار.
يمكنك أيضًا استخدام هذا الرمز للحصول على قائمة السلاسل من استعلام SQLite أو من ملف CSV.
لتحرير عدد أقصى صفوف من القائمة التي عليك فقط تحريرها max_row.
إذا قمت بالضغط على إدخال البرنامج ، فسيقوم بطباعة قيمة السلسلة المحددة وموضعها.

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()
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top