首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Linux上的Tkinter Ctrl+Shift+Z

Linux上的Tkinter Ctrl+Shift+Z
EN

Stack Overflow用户
提问于 2022-03-13 12:25:32
回答 1查看 124关注 0票数 0

我想在Linux (Wayland)上使用Tkinter在GUI应用程序中实现一个定制的重做功能。

这是我目前的代码:

代码语言:javascript
复制
"""Plotting canvas."""

from PIL import Image
from PIL.ImageTk import PhotoImage
from tkinter import NW
from tkinter import Canvas
from tkinter import Event
from tkinter import Tk

from diffusion_scribbles.functions import overlay
from diffusion_scribbles.gui.colors import BLUE, RED
from diffusion_scribbles.selections import DiffusionSelection, Selection
from diffusion_scribbles.types import Color, Dataset, Vector2D


__all__ = ['PlotCanvas']


class PlotCanvas(Canvas):
    """Image canvas."""

    def __init__(self, root: Tk, width: int, height: int, **kwargs):
        super().__init__(root, width=width, height=height, **kwargs)
        self.width = width
        self.height = height
        self.selection_method: Selection = DiffusionSelection(width, height)
        self.bind("<Button-1>", self.start_draw)
        self.bind("<B1-Motion>", self.draw)
        self.bind("<ButtonRelease-1>", self.stop_draw)
        root.bind('<Control-z>', self.undo)
        root.bind('<Control-Shift-KeyPress-z>', self.redo)
        self._dataset: Dataset | None = None
        self._data_points: Image.Image | None = None
        self._scribble: Image.Image | None = None
        self._image: Image.Image | None = None
        self._photo_image: PhotoImage | None = None
        self.primary_color: Color = RED
        self.secondary_color: Color = BLUE

    @property
    def dataset(self) -> Dataset | None:
        """Returns the dataset."""
        return self._dataset

    @dataset.setter
    def dataset(self, dataset: Dataset) -> None:
        """Sets the dataset."""
        self._dataset = dataset
        self._scribble = None
        self.image = self._data_points = dataset.draw(
            (self.width, self.height)
        )

    @property
    def data_points(self) -> Image.Image:
        """Returns the data points image."""
        return self._data_points

    @data_points.setter
    def data_points(self, data_points: Image.Image) -> None:
        """Sets the data points image."""
        self._data_points = data_points
        self.image = overlay(data_points, self.scribble)

    @property
    def scribble(self) -> Image.Image:
        """Returns the scribble image."""
        return self._scribble

    @scribble.setter
    def scribble(self, scribble: Image.Image) -> None:
        """Sets the scribble image."""
        self._scribble = scribble
        self.image = overlay(self.data_points, scribble)

    @property
    def image(self) -> Image.Image:
        """Returns the currently displayed image."""
        return self._image

    @image.setter
    def image(self, image: Image.Image) -> None:
        """Sets the currently displayed image."""
        self._image = image
        self.photo_image = PhotoImage(self._image)

    @property
    def photo_image(self) -> PhotoImage:
        """Returns the current photo image."""
        return self._photo_image

    @photo_image.setter
    def photo_image(self, photo_image: PhotoImage) -> None:
        """Sets the current photo image."""
        self._photo_image = photo_image
        self.create_image(0, 0, anchor=NW, image=self._photo_image)

    def start_draw(self, event: Event) -> None:
        """Start drawing a line."""
        if self.dataset:
            self.selection_method.start(
                Vector2D(event.x, event.y),
                self.primary_color,
                self.secondary_color
            )

    def draw(self, event: Event) -> None:
        """Draw lines."""
        if not self.dataset:
            return

        self.scribble = self.selection_method.move(Vector2D(event.x, event.y))

    def stop_draw(self, _: Event) -> None:
        """Stop drawing a line."""
        if not self.dataset:
            return

        self.selection_method.stop()
        self.data_points = self.selection_method.colorize(self.dataset)

    def undo(self, _: Event) -> None:
        """Undo last action."""
        self.scribble = self.selection_method.undo()
        self.data_points = self.selection_method.colorize(self.dataset)

    def redo(self, _: Event) -> None:
        """Undo last action."""
        print('Redo.', flush=True)

虽然undo工作得很好,但是当我按下适当的Ctrl+Shift+Z键组合时,就不会执行Ctrl+Shift+Z。我还尝试了其他变体,如'<Control-Shift-z>''<Shift-Control-KeyPress-z>''<Control-Shift-KeyPress-z>',但都没有效果。

如何将键组合Ctrl+Shift+Z绑定到Wayland下的Linux上的自定义重做操作?

最小可重现性示例

代码语言:javascript
复制
from functools import partial
from tkinter import Tk


class Window(Tk):

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.bind('<Control-z>', partial(print, 'Undo'))
        self.bind('<Control-Shift-KeyPress-z>', partial(print, 'Redo'))


if __name__ == '__main__':
    Window().mainloop()
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-03-13 13:57:45

如果我使用大写Z而不是Shift-z (用小写z),代码对我有效。

代码语言:javascript
复制
import tkinter as tk

def test1(event):
    print('test1:', event)

def test2(event):
    print('test2:', event)
    
root = tk.Tk()

root.bind('<Control-z>', test1)  # Control+Z
root.bind('<Control-Z>', test2)  # Control+Shift+Z

root.mainloop()

如果我使用'<Control-Shift-Z>',那么它也能工作,因为有大写的Z

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71456737

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档