You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Python Arcade库的文本框滚动功能实现求助

Solution for Arcade Text Box Scrolling

Hey there! Let's fix that text overflow and scrolling issue in your Arcade text box. The main gap right now is that your display class draws the entire text string no matter the box width—we need to track which portion of the text should be visible, and adjust that portion when the cursor moves outside the visible area.

Key Concepts to Make This Work

  • Calculate the width of a single character (using Arcade's built-in text width tools) to know when text exceeds the box.
  • Add a scroll_offset variable to your display class to track the starting index of the visible text.
  • Adjust scroll_offset dynamically based on the cursor position to keep the cursor within the text box bounds.
  • Only draw the substring of text that fits within the box, starting from scroll_offset.

Modified Code Implementation

First, update your Text Display Class to handle scrolling:

class TextDisplay:
    def __init__(self, x, y, width, char_limit, font_size=24):
        self.x = x
        self.y = y
        self.width = width
        self.font_size = font_size
        self.highlighted = False
        self.text = ""
        self.symbol = ""
        self.char_limit = char_limit
        
        # Calculate width of a single character (using 'A' as a baseline)
        self.char_width = arcade.get_text_width("A", font_size=font_size)
        # Max number of visible characters in the box
        self.max_visible_chars = int(self.width // self.char_width)
        # Track the starting index of visible text
        self.scroll_offset = 0

    def update(self, delta_time, text, cursor_index):
        self.text = text
        # Adjust scroll offset to keep cursor visible
        self.adjust_scroll_offset(cursor_index)

    def adjust_scroll_offset(self, cursor_index):
        # If cursor is to the right of visible area, shift scroll right
        if cursor_index >= self.scroll_offset + self.max_visible_chars:
            self.scroll_offset = cursor_index - self.max_visible_chars + 1
            # Don't let offset go negative or beyond text length
            self.scroll_offset = max(0, min(self.scroll_offset, len(self.text)))
        # If cursor is to the left of visible area, shift scroll left
        elif cursor_index < self.scroll_offset:
            self.scroll_offset = cursor_index

    def draw_text(self):
        # Get the visible substring of text
        visible_text = self.text[self.scroll_offset:self.scroll_offset + self.max_visible_chars]
        # Draw the visible text (plus cursor if highlighted)
        draw_text = visible_text + (self.symbol if self.highlighted else "")
        arcade.draw_text(
            draw_text,
            self.x - self.width/2,
            self.y,
            arcade.color.BLACK,
            font_size=self.font_size,
            anchor_y="center"
        )

Then, update your Text Box Class to pass the cursor index instead of just the symbol to the display:

def update(self, delta_time, keys_pressed):
    if self.text_display.highlighted:
        text, cursor_index = self.text_storage.update(delta_time, keys_pressed)
        # Update symbol based on blink state from storage
        self.text_display.symbol = self.text_storage.cursor_symbol
        self.text_display.update(delta_time, text, cursor_index)

And tweak your Text Storage Class to return the cursor index (instead of just the symbol) and fix text insertion/backspace logic:

def update(self, delta_time, keys_pressed):
    self.time += delta_time
    self.blink_cursor()
    for key in keys_pressed:
        if key == arcade.key.BACKSPACE:
            if len(self.text) > 0:
                # Adjust cursor if deleting the character before it
                if self.cursor_index > 0:
                    self.text = self.text[:self.cursor_index-1] + self.text[self.cursor_index:]
                    self.cursor_index -= 1
        elif key == arcade.key.LEFT:
            if self.cursor_index > 0:
                self.cursor_index -= 1
        elif key == arcade.key.RIGHT:
            if self.cursor_index < len(self.text):
                self.cursor_index += 1
        else:
            if len(self.text) < self.char_limit:
                # Insert character at cursor position instead of appending
                self.text = self.text[:self.cursor_index] + chr(key) + self.text[self.cursor_index:]
                self.cursor_index += 1
    # Return text and cursor index for display scrolling logic
    return self.text, self.cursor_index

How This Works

  1. Character Width Calculation: We use arcade.get_text_width to find the width of a standard character, which lets us compute exactly how many characters fit in the text box.
  2. Scroll Offset Adjustment: The adjust_scroll_offset method checks if the cursor is outside the current visible text range. If it is, we shift the scroll_offset to bring the cursor back into view.
  3. Visible Text Drawing: Instead of drawing the full text, we slice it to only include characters starting from scroll_offset up to the maximum visible count.
  4. Cursor Handling: We fixed text insertion to add characters at the cursor position (instead of always appending) and adjusted backspace to update the cursor position correctly when deleting text.

Now when you type text longer than the box width, the text will scroll automatically as you type, and pressing left/right arrows will shift the visible text to keep the cursor in view.

内容的提问来源于stack exchange,提问作者Wamiq Ur Rehman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 07:36:55