杰瑞科技汇

screen.split python

Of course! The screen.split() method in Python is a powerful tool for splitting a terminal screen into multiple rectangular regions, often called "panes" or "splits". This is a core feature of the curses library, which provides a terminal-independent way to create text-based user interfaces (TUIs).

screen.split python-图1
(图片来源网络,侵删)

Let's break down how it works, from a simple example to a detailed explanation.

The Core Concept: newwin()

Instead of screen.split(), the curses library uses a more direct approach:

  1. You get the main screen window with stdscr = curses.initscr().
  2. You create new, smaller windows on top of that main screen using stdscr.subwin(height, width, start_y, start_x) or newwin(height, width, start_y, start_x).
  3. You then draw content independently into each of these new windows.

The term "split" is a conceptual one. You are literally splitting the main screen's real estate into multiple curses window objects.


Complete, Runnable Example

This example will split the screen into four equal panes and draw a box and some text in each one.

screen.split python-图2
(图片来源网络,侵删)
import curses
import time
def main(stdscr):
    # 1. Initialize curses settings
    curses.curs_set(0)  # Hide the cursor
    stdscr.clear()      # Clear the screen
    # 2. Get the screen dimensions
    height, width = stdscr.getmaxyx()
    # 3. Define the dimensions and positions for each pane
    # We'll create a 2x2 grid
    pane_height = height // 2
    pane_width = width // 2
    # Top-left pane
    win1 = stdscr.subwin(pane_height, pane_width, 0, 0)
    # Top-right pane
    win2 = stdscr.subwin(pane_height, pane_width, 0, pane_width)
    # Bottom-left pane
    win3 = stdscr.subwin(pane_height, pane_width, pane_height, 0)
    # Bottom-right pane
    win4 = stdscr.subwin(pane_height, pane_width, pane_height, pane_width)
    # 4. Add content to each pane
    # --- Pane 1 ---
    win1.border()  # Add a border
    win1.addstr(1, 2, "Top-Left Pane")
    win1.addstr(2, 2, f"Size: {pane_height}x{pane_width}")
    win1.refresh() # IMPORTANT: Refresh each window to draw its content
    # --- Pane 2 ---
    win2.border()
    win2.addstr(1, 2, "Top-Right Pane")
    win2.addstr(2, 2, f"Size: {pane_height}x{pane_width}")
    win2.refresh()
    # --- Pane 3 ---
    win3.border()
    win3.addstr(1, 2, "Bottom-Left Pane")
    win3.addstr(2, 2, f"Size: {pane_height}x{pane_width}")
    win3.refresh()
    # --- Pane 4 ---
    win4.border()
    win4.addstr(1, 2, "Bottom-Right Pane")
    win4.addstr(2, 2, f"Size: {pane_height}x{pane_width}")
    win4.refresh()
    # Add a message at the bottom of the main screen
    stdscr.addstr(height - 1, 2, "Press any key to exit...")
    stdscr.refresh()
    # Wait for user input before exiting
    stdscr.getch()
if __name__ == "__main__":
    # The wrapper function handles setup and teardown
    curses.wrapper(main)

How to Run It:

  1. Save the code as a Python file (e.g., split_screen.py).
  2. Run it from your terminal: python split_screen.py
  3. You will see the four panes. Press any key to exit.

Detailed Breakdown of the Code

curses.wrapper(main)

This is the recommended way to start any curses application. It handles:

  • Initializing curses (curses.initscr()).
  • Setting up the terminal correctly.
  • Calling your main function with the main screen window (stdscr) as an argument.
  • Ensuring that curses.endwin() is called to restore your terminal to its normal state, even if your program crashes.

stdscr.getmaxyx()

This function returns a tuple (height, width) representing the size of the terminal window. This is crucial for calculating the size and position of your splits.

stdscr.subwin(height, width, start_y, start_x)

This is the key function for creating a "split". It creates a new window of a specific size at a specific position.

  • height: The number of rows for the new window.
  • width: The number of columns for the new window.
  • start_y: The row coordinate of the top-left corner.
  • start_x: The column coordinate of the top-left corner.

Important Note: The coordinates are (y, x), which corresponds to (row, column). This is different from the Cartesian (x, y) coordinates you might be used to.

screen.split python-图3
(图片来源网络,侵删)

Drawing and Refreshing

Each window you create (win1, win2, etc.) is an independent drawing surface.

  • Drawing Functions: You use methods like addstr(y, x, "text"), border(), mvprintw(y, x, "format", ...), etc., on the specific window object you want to modify.
  • window.refresh(): This is essential. When you call a drawing function, it changes an internal buffer for that window. refresh() pushes those changes to the physical screen. If you forget to refresh a window, its content will never appear.

Common Splitting Patterns

Here are some other common ways to split the screen.

Vertical Split (Left and Right)

import curses
def main(stdscr):
    curses.curs_set(0)
    stdscr.clear()
    height, width = stdscr.getmaxyx()
    # Define a 70/30 split
    left_width = int(width * 0.7)
    right_width = width - left_width
    # Create left pane
    left_win = stdscr.subwin(height, left_width, 0, 0)
    left_win.border()
    left_win.addstr(1, 2, "Left Pane (70%)")
    left_win.refresh()
    # Create right pane
    right_win = stdscr.subwin(height, right_width, 0, left_width)
    right_win.border()
    right_win.addstr(1, 2, "Right Pane (30%)")
    right_win.refresh()
    stdscr.addstr(height - 1, 2, "Press any key to exit...")
    stdscr.refresh()
    stdscr.getch()
if __name__ == "__main__":
    curses.wrapper(main)

Horizontal Split (Top and Bottom)

import curses
def main(stdscr):
    curses.curs_set(0)
    stdscr.clear()
    height, width = stdscr.getmaxyx()
    # Define a 60/40 split
    top_height = int(height * 0.6)
    bottom_height = height - top_height
    # Create top pane
    top_win = stdscr.subwin(top_height, width, 0, 0)
    top_win.border()
    top_win.addstr(1, 2, "Top Pane (60%)")
    top_win.refresh()
    # Create bottom pane
    bottom_win = stdscr.subwin(bottom_height, width, top_height, 0)
    bottom_win.border()
    bottom_win.addstr(1, 2, "Bottom Pane (40%)")
    bottom_win.refresh()
    stdscr.addstr(height - 1, 2, "Press any key to exit...")
    stdscr.refresh()
    stdscr.getch()
if __name__ == "__main__":
    curses.wrapper(main)

Advanced: Handling Window Resizing

If the user resizes their terminal, your application will break. To handle this, you can catch the SIGWINCH signal (which is sent when the terminal is resized).

import curses
import signal
import time
def handle_resize(signum, frame):
    """This function will be called on terminal resize."""
    # We don't do anything here, just set a flag.
    # The main loop will handle the redraw.
    global needs_redraw
    needs_redraw = True
def main(stdscr):
    global needs_redraw
    needs_redraw = False
    # Set up the signal handler for window resize
    signal.signal(signal.SIGWINCH, handle_resize)
    while True:
        if needs_redraw:
            stdscr.clear()
            height, width = stdscr.getmaxyx()
            # --- Redraw all your panes here ---
            # (Use the same logic as the first example)
            pane_height = height // 2
            pane_width = width // 2
            for i in range(2):
                for j in range(2):
                    win = stdscr.subwin(pane_height, pane_width, i * pane_height, j * pane_width)
                    win.border()
                    win.addstr(1, 2, f"Pane {i},{j}")
                    win.refresh()
            needs_redraw = False
        stdscr.addstr(height - 1, 2, "Press 'q' to quit. Resize the terminal.")
        stdscr.refresh()
        key = stdscr.getch()
        if key == ord('q'):
            break
if __name__ == "__main__":
    curses.wrapper(main)

Key Takeaways

  1. screen.split() is not a real function. The concept is achieved by creating multiple curses windows using stdscr.subwin() or newwin().
  2. Coordinates are (y, x) (row, column).
  3. Always refresh() each window after drawing to it to make the changes visible.
  4. Use curses.wrapper() for robust application setup and teardown.
  5. Use stdscr.getmaxyx() to get the current screen size, which is essential for responsive layouts.
  6. For complex applications, consider using a higher-level library built on curses, like urwid, npyscreen, or textual, which provide more powerful and easier-to-use layout managers.
分享:
扫描分享到社交APP
上一篇
下一篇