Как мне синхронизировать прокрутку двух многострочных текстовых полей в wxPython?

Вопрос или проблема

В настоящее время я разрабатываю приложение с использованием wxPython на Python 3.12. Приложение содержит два многострочных текстовых поля, расположенных рядом: поле слева принимает ввод от пользователя, а поле справа заполняется программой с учетом конкретной строки обратной связи о вводе пользователя.
Изображение графического пользовательского интерфейса

Когда пользователь вводит текст, превышающий определенное количество строк, в каждом поле появляются полосы прокрутки, но когда пользователь прокручивает одно поле, другое остается неподвижным, что приводит к несоответствию обратной связи и затрудняет определение места, где программа указывает на найденную проблему.

Обширные интернет-исследования не принесли никаких работающих решений этой проблемы. Эта страница Как синхронизировать полосы прокрутки двух сеток в wx содержит похожую, но не идентичную проблему. Однако она использует Python 2, и в результате код больше не компилируется в что-то полезное. Может кто-то помочь? Спасибо!

### Pottersclay Writing Assistant 2.2a (MRE) ###
import wx
# Инициализация окна
app = wx.App()
window = wx.Frame(None, title = "Pottersclay Writing Assistant 2.2a (MRE)", size = (1885, 1010))
window.Show()
bkg = wx.Panel(window, style = wx.WANTS_CHARS)
# Создание двух основных текстовых полей и установка их стилей
contents = wx.TextCtrl(bkg, pos = (0, 35), size = (500, 400), style = wx.TE_MULTILINE | wx.HSCROLL | wx.WANTS_CHARS)
outputbox = wx.TextCtrl(bkg, pos = (0, 35), size = (500, 400), style = wx.TE_MULTILINE | wx.HSCROLL | wx.WANTS_CHARS | wx.TE_READONLY)
contents.SetWindowStyle(contents.GetWindowStyle() & ~ wx.TAB_TRAVERSAL)
outputbox.SetWindowStyle(outputbox.GetWindowStyle() & ~ wx.TAB_TRAVERSAL)
EXAMPLE = "0\n1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n21\n22\n23\n24\n25\n26\n27\n28\n29\n30\n31\n32\n33\n34\n35\n36\n37\n38\n39\n40\n41\n42\n43\n44\n45\n46\n47\n48\n49\n"
contents.SetValue(EXAMPLE)
outputbox.SetValue(EXAMPLE)
# Добавление двух текстовых полей и кнопочного блока в новый горизонтальный бокс-упаковщик, представляющий все окно под командной строкой
lowerhbox = wx.BoxSizer(wx.HORIZONTAL)
lowerhbox.Add(contents, proportion = 1, flag = wx.EXPAND | wx.BOTTOM | wx.LEFT, border = 5)
lowerhbox.Add(outputbox, proportion = 1, flag = wx.EXPAND | wx.BOTTOM | wx.RIGHT, border = 5)
bkg.SetSizer(lowerhbox)
app.MainLoop()

Ответ или решение

Синхронизация прокрутки двух многострочных текстовых полей в wxPython может быть несколько сложной задачей, но с правильным подходом это вполне осуществимо. Давайте рассмотрим, как можно эффективно реализовать эту функциональность в вашем приложении на Python 3.12.

Введение

Ваше приложение, в котором два текстовых поля отображают пользовательский ввод и соответствующие ответы, требует синхронизации прокрутки. Это важно для удобства пользователя, чтобы он мог легко сопоставлять вводимую информацию с обратной связью.

Решение

Для синхронизации прокрутки двух текстовых полей необходимо установить обработчики событий для каждого текстового поля, чтобы они обновляли прокрутку друг друга. Мы будем использовать метод GetScrollPos() для получения текущей позиции прокрутки и SetScrollPos() для установки положения.

Шаги реализация

  1. Создайте новое приложение wxPython.
  2. Сконструируйте интерфейс с двумя текстовыми полями.
  3. Добавьте обработчики событий для прокрутки.
  4. Обновите прокрутку второго текстового поля в соответствии с прокруткой первого, и наоборот.

Пример кода

Ниже приведён пример кода, который демонстрирует вышеописанные шаги:

import wx

class SyncScrollFrame(wx.Frame):
    def __init__(self):
        super().__init__(None, title="Синхронизация прокрутки", size=(1000, 500))

        self.bkg = wx.Panel(self)
        self.layout = wx.BoxSizer(wx.HORIZONTAL)

        self.contents = wx.TextCtrl(self.bkg, style=wx.TE_MULTILINE | wx.HSCROLL)
        self.outputbox = wx.TextCtrl(self.bkg, style=wx.TE_MULTILINE | wx.HSCROLL | wx.TE_READONLY)

        self.layout.Add(self.contents, 1, wx.EXPAND | wx.ALL, 5)
        self.layout.Add(self.outputbox, 1, wx.EXPAND | wx.ALL, 5)

        self.bkg.SetSizer(self.layout)

        # Привязка событий прокрутки
        self.contents.Bind(wx.EVT_SCROLLWIN, self.OnScrollContents)
        self.outputbox.Bind(wx.EVT_SCROLLWIN, self.OnScrollOutputbox)

        self.Show()

    def OnScrollContents(self, event):
        # Получение текущей позиции прокрутки
        pos = self.contents.GetScrollPos(wx.VERTICAL)
        self.outputbox.SetScrollPos(wx.VERTICAL, pos)
        event.Skip()  # Обработка события для дальнейшей прокрутки

    def OnScrollOutputbox(self, event):
        pos = self.outputbox.GetScrollPos(wx.VERTICAL)
        self.contents.SetScrollPos(wx.VERTICAL, pos)
        event.Skip()  # Обработка события для дальнейшей прокрутки

if __name__ == "__main__":
    app = wx.App(False)
    SyncScrollFrame()
    app.MainLoop()

Объяснение кода

  • Класс SyncScrollFrame: Это основной класс окна, который наследует от wx.Frame. В конструкторе мы создаем две текстовые области и добавляем их в горизонтальный слайзер.
  • Обработчики события прокрутки: Мы используем OnScrollContents и OnScrollOutputbox, которые отслеживают события прокрутки. При прокрутке одного текстового поля другая текстовая область синхронизируется с ним.
  • Методы GetScrollPos и SetScrollPos: Используя эти методы, мы получаем текущее положение прокрутки и устанавливаем это значение для другого текстового поля.

Заключение

Теперь у вас есть приложение wxPython, в котором два многострочных текстовых поля синхронизированы по прокрутке. Это обеспечивает пользователям удобный опыт, позволяющий легко сопоставлять вводимую информацию с отображаемой обратной связью. Не стесняйтесь экспериментировать с дополнительными функциональными возможностями, такими как настройка стилей и добавление других интерактивных элементов для повышения удобства использования.

Оцените материал
Добавить комментарий

Капча загружается...