5

サブウィンドウを使用するcursesアプリケーションがありますが、それらを削除できないようです。

たとえば、このコードは機能しません。

import curses
def fill(window, ch):
    y, x = window.getmaxyx()
    s = ch * (x - 1)
    for line in range(y):
        window.addstr(line, 0, s)

def main(stdscr):
    fill(stdscr, 'M')
    stdscr.refresh()
    stdscr.getch()

    subwin = stdscr.subwin(1, 28, 20, 13)
    fill(subwin, 'J')
    subwin.refresh()
    subwin.getch()

    del subwin
    stdscr.touchwin()
    stdscr.refresh()
    stdscr.getch()

curses.wrapper(main)

このコードを実行すると、画面は「M」で埋められ、キーを押すと、サブウィンドウが作成され、「J」で埋められます。最後に、もう一度キーを押すと、コードはサブウィンドウを削除し、画面を完全に再描画します。ただし、それらのJはまだそこにあります。

いくつかの実験の結果、stdscrのclear()メソッドを呼び出すとサブウィンドウが機能することがわかりましたが、背景を空白にして書き直さずに、元の状態に戻したいと思います。誰かがこれを行うことができる方法を知っていますか?

4

2 に答える 2

10

サブウィンドウを使用している正当な理由はありますか?新しいトップレベルウィンドウを作成すると、コードは正しく機能します。に変更stdscr.subwinするだけcurses.newwinで、期待どおりに機能します。

私は呪いの専門家ではありませんが、サブウィンドウがその親と文字バッファを共有しているため、どちらか一方を変更するともう一方にも影響すると思います。したがって、ウィンドウを論理領域(おそらくメニューバー、メイン領域、ステータスバー)に分割する場合は、サブウィンドウが便利です。ただし、ダイアログボックスやポップアップメニューのようなものを探している場合は、まったく新しいウィンドウ(独自の個別のバッファを備えた)が必要です。

私に賛成または反対するncursesの明確なリファレンスは見つかりませんが、AIXのマニュアルページはそれを裏付けているようです。

サブウィンドウがその親のウィンドウバッファを共有していることを思い出してください。親ウィンドウまたはそのサブウィンドウのいずれかを介して、サブウィンドウでカバーされる領域の共有ウィンドウバッファーに加えられた変更は、ウィンドウバッファーを共有するすべてのウィンドウに影響します。

もちろん、これはncursesにとって決定的なものではありませんが、それとは反対のことは何も見つかりません。確かに、観察された動作を説明しているようです。また、大まかな実験を行いました。ここでは、例の行の直後に、次のsubwin.getch()行を追加しました。

raise Exception(stdscr.instr(20, 15, 3))

あなたの例でJJJは、実際のメインウィンドウのコンテンツとして取得します。curses.newwin()代わりにウィンドウの作成に使用するように変更するとstdscr.subwin()、期待どおりの結果が得られMMMます。

特定のPythoncursesリソースがいくつあるかはわかりませんが、ncursesに関する標準的なチュートリアルとドキュメントのほとんどは、この種のレベルで非常に役立ちます。その中でいくつかの作業をしなければならなかったとき、このドキュメントは非常に役に立ちました。[例]セクションまで下にスクロールすると、メニューポップアップがサブウィンドウではないことがわかります。彼は次の少し漠然とした説明でこれをほのめかしています。

この新しいウィンドウが、背景に以前に書き込まれた文字を上書きすることは望ましくありません。メニューが閉じた後、彼らはそこにとどまるはずです。これが、メニューウィンドウをstdscrのサブウィンドウとして作成できない理由です。

stdscrまた、両方と独自のウィンドウを使用すると問題が発生する可能性があることを覚えています。「公式の」ncursesの紹介には、この種のことについていくつかの警告があります。また、明らかにエラーが発生しやすいため、ウィンドウのオーバーラップを完全に回避することをお勧めしますが、短期間の一時的なモーダルダイアログ(私がそれらを使用する唯一の用途)で問題が発生したことを覚えていません。もちろん、私の単純なユースケースで問題が明らかにならなかったからといって、問題がないというわけではありません。しかし、ncursesのように複雑なものでは、物事をできるだけ単純に保つことの知恵を見ることができます。

それがお役に立てば幸いです。私が言ったように、私は決して呪いの専門家ではありませんが、うまくいけば、これはあなたをさらに一歩前進させるでしょう。

于 2013-02-06T15:56:43.053 に答える
1

このコードには2つの問題があります。

まず、前のポスターで述べたように、サブウィンドウは親ウィンドウとバッファーを共有するためcurses.newwin()、完全に独立したウィンドウが必要な場合はを使用する必要があります。

第二にdel、ウィンドウを削除するために使用することは、正しく機能するために参照カウント/ガベージコレクションに依存しているため、問題があります。(1つには、ウィンドウを機能させるために、ウィンドウへのすべての参照を削除する必要があります。)curses.panelモジュールを使用してウィンドウを明示的に表示/非表示にすることをお勧めします。

于 2014-12-09T05:07:48.833 に答える