我想在Linux (Wayland)上使用Tkinter在GUI应用程序中实现一个定制的重做功能。
这是我目前的代码:
"""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上的自定义重做操作?
最小可重现性示例
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()发布于 2022-03-13 13:57:45
如果我使用大写Z而不是Shift-z (用小写z),代码对我有效。
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。
https://stackoverflow.com/questions/71456737
复制相似问题