2011-10-16 38 views
5

Làm cách nào để ngăn chặn khả năng người dùng cuối chỉnh sửa/thêm/xóa văn bản trong một tiện ích Văn bản? (Python v3.2 .. và tkinter)Chỉ đọc Tiện ích văn bản trong python3-tkinter; nền tảng chéo

Điểm là chỉ ngăn chặn khả năng thay đổi/thêm/xóa văn bản nhưng không được đúc các tính năng khác. Có lẽ một văn bản NoEdit được mở rộng sẽ là một tên tốt hơn.

Tôi đã thử .text [ 'nhà nước'] = 'disabled' và nó hoạt động gần OK trong Windows (nó vẫn cho phép người dùng lựa chọn/sao chép văn bản nhấn mạnh việc lựa chọn, trang lên/xuống và lên Các nút/xuống chỉ hoạt động. Điều duy nhất bị hỏng dường như là con trỏ được ẩn.)

Nhưng trên mọi thứ đều bị hỏng. Không nổi bật, không chọn/sao chép, ... Ugh

Kể từ Tkinter có thực tế không có tài liệu hướng dẫn bằng Python, tôi đã tìm kiếm và tìm thấy một số TCL tư vấn, để lấy được một lớp mới và ngăn chặn các chènxóa chức năng.

Vì vậy, tôi đã cố gắng như vậy:

class roText(tk.Text): 
    def insert(self,*args,**kwargs): 
     print(" Hey - Im inside roText.insert") 
     pass 
    def delete(self,*args,**twargs): 
     pass  
    def pInsert(self,*args,**twargs): 
     super().insert(*args,**twargs) 

Đáng tiếc là nó đã không làm việc đúng. Rõ ràng tkinter không sử dụng các chức năng chèn và xóa khi người dùng cuối nhập/xóa mã. Có lẽ những chèn/xóa TCL là cái gì khác, và tôi bị mất một cái gì đó trong bản dịch từ TCL và Swahili. Tkinter.Text sử dụng chức năng gì cho văn bản chỉnh sửa người dùng cuối? Hy vọng rằng họ không phải là nội bộ ...

Vì vậy, có cách nào sửa đổi tiện ích Văn bản để chỉ chặn chỉnh sửa người dùng cuối không? Có cách nào để làm điều đó mà không cần lặn bên trong và ghi đè mã Tkinter nội bộ, vì vậy công cụ không bị hỏng bởi các phiên bản tiếp theo của Tkinter?

Nhìn vào cửa sổ trình bao Idle, tôi thấy rằng họ đã quản lý để chặn các chỉnh sửa (ngoại trừ dòng cuối cùng). Vì vậy, có một cách. Nhưng nó là gì và tốn kém như thế nào?

Trả lời

2

Lý do trạng thái disabled dường như không hoạt động trên Mac là do nó tắt ràng buộc cung cấp tiêu điểm cho tiện ích. Không tập trung, việc đánh dấu trên máy Mac không hiển thị. Nếu bạn đặt trạng thái thành disabled nhưng sau đó gán một ràng buộc cho <ButtonPress-1> để đặt trọng tâm rõ ràng cho tiện ích văn bản đã tắt, bạn có thể chọn và sao chép văn bản và đánh dấu sẽ hiển thị.

Đối với con trỏ biến mất ... được cho là, đó là những gì được cho là xảy ra. Con trỏ cho người dùng biết "đây là nơi văn bản sẽ được chèn". Vì không có văn bản nào được chèn vào, nên đầu mối trực quan đó sẽ gây nhầm lẫn cho người dùng. Những gì bạn có thể làm thay vào đó, nếu nó thực sự quan trọng, là để chèn một hình ảnh nhỏ bất cứ nơi nào họ bấm vào để mô phỏng con trỏ.

Để trả lời câu hỏi của bạn về việc tiện ích có thực sự sử dụng phương thức insertdelete hay không: các phương pháp trên tiện ích con thực tế là những ràng buộc mặc định sử dụng, để ghi đè chúng trong lớp con không có hiệu lực. Bạn sẽ cần phải làm lại tất cả các ràng buộc mặc định cho rằng để làm việc. Đó là doable, nhưng rất nhiều công việc.

Thật không may, đây là một lĩnh vực mà lập trình trong Tcl thực sự tỏa sáng, bởi vì bạn có thể chỉ cần tắt các lệnh insertdelete của tiện ích. Tất nhiên, bạn có thể làm điều đó trực tiếp trong Tkinter kể từ cuối cùng nó chạy mã tcl để làm mọi thứ, nhưng điều đó sẽ liên quan đến việc viết một số mã tcl mà không phải là một giải pháp rất tốt từ quan điểm của một coder Python.

Tôi nghĩ giải pháp tốt nhất là sử dụng trạng thái bị vô hiệu hóa, sau đó chỉ thêm các liên kết vừa đủ để thực hiện những gì bạn muốn.

Dưới đây là một ví dụ đơn giản hoạt động bằng cách đặt tiêu điểm rõ ràng lên nhấp chuột. Với mã này tôi có thể nhấp chuột phải và swipe để chọn một khu vực, hoặc đúp hoặc triple-click để chọn từ và dòng:

import Tkinter as tk 

class SampleApp(tk.Tk): 
    def __init__(self, *args, **kwargs): 
     tk.Tk.__init__(self, *args, **kwargs) 
     self.text = tk.Text(width=40, height=20) 
     self.text.bind("<1>", self.set_focus) 
     self.text.insert("end", "\n".join(dir(tk.Tk))) 
     self.text.configure(state="disabled") 
     self.text.pack(fill="both", expand=True) 

    def set_focus(self, event): 
     '''Explicitly set focus, so user can select and copy text''' 
     self.text.focus_set() 

if __name__ == "__main__": 
    app = SampleApp() 
    app.mainloop() 
+0

OK, tôi đã có cơ hội thử nghiệm trên Mac và văn bản.focus_set() bị ràng buộc là <1> khắc phục được sự cố, giống như bạn đã nói. ** Cảm ơn !!! ** (Có lẽ trang này có thể được dọn dẹp cho những người khác đang tìm kiếm giải pháp. Và tôi đã thấy nhiều trên web). Thật không may là tôi sợ rằng nó dường như là một trong nhiều vấn đề với cổng Tkinter cho Mac. màu 'xanh' không hoạt động trên các nút, văn bản trên các nút cần thêm khoảng cách (văn bản này có thể liên quan đến độ phân giải), v.v ... Những thứ này dễ làm việc và tôi chỉ hy vọng sẽ không hiển thị – Momus

-1

@BryanOakley Tôi đã mất một thời gian để kiểm tra đề xuất của bạn kể từ khi tôi có không có máy Mac. Thật không may Mac thực hiện Python là lỗi. tập trung tôi đã thêm, tức là chức năng vô hiệu hóa của tôi mà tôi gọi là sau khi tạo một cửa sổ và chèn văn bản, bây giờ gọi đầu tiên:

self.txt['state'] = 'disabled' 

và sau đó

self.txt.focus_set() 

Đó là những gì tôi nghĩ rằng bạn đã đề nghị.

Đó là "loại" đã hoạt động. Tức là: khi chọn văn bản (nhấp và kéo hoặc nhấp đúp) làm nổi bật nhất thời gian. Python phải có một số tham chiếu bộ nhớ xấu hoặc các lỗi như vậy: Đôi khi làm nổi bật không hoạt động lúc đầu, sau đó nó bắt đầu hoạt động (trong cùng một cửa sổ) sau khi nhấp chuột nhiều hơn. Đôi khi khi chương trình được gọi nó hoạt động đúng của con dơi. Đôi khi việc chọn bằng phím Shift-rightArrow sẽ hoạt động nhưng việc chọn bằng chuột sẽ không hoạt động. Sau đó bắt đầu làm việc trở lại. Hoặc nó sẽ hoạt động tốt trong một cửa sổ nhưng không hoạt động trong một cửa sổ khác (cả hai cùng một lớp), sau đó bắt đầu làm việc trong tất cả các cửa sổ ... vv ...

Điều tốt là thêm tiêu điểm không ảnh hưởng xấu đến Windows Tôi đoán tại thời điểm này tôi sẽ chỉ hy vọng rằng bản phát hành tương lai/kế tiếp của Python dành cho Mac sẽ sửa các lỗi đó ..

BTW, có vẻ như Mac là một chút của một đứa trẻ mồ côi cho Python. Việc triển khai thực hiện xấu hơn nhiều so với Windows, có nghĩa là phông chữ trông tồi tệ hơn, các nút, v.v. Hoặc có thể do các độ phân giải màn hình và các cổng Python khác nhau không phù hợp với các độ phân giải màn hình và cổng Python. Cảm ơn sự giúp đỡ và gợi ý của bạn để sử dụng trọng tâm cho Mac.

+0

Bạn cần để gọi 'focus_set' trong hàm gọi lại cho sự kiện' <1> ', không chỉ khi bạn tạo tiện ích. Nhìn từ câu trả lời của bạn, bạn chỉ thiết lập tiêu điểm một lần. Tôi lặp lại: để làm nổi bật hiển thị, tiện ích phải có tiêu điểm. Nếu bạn tập trung vào nó, nó có thể mất tập trung bất cứ khi nào bạn nhấp vào bất cứ nơi nào khác. Việc thêm một ràng buộc vào '<1> 'để đặt tiêu điểm sẽ đảm bảo tiêu điểm luôn luôn tập trung khi bạn cố gắng thực hiện lựa chọn (vì mọi lựa chọn luôn bắt đầu bằng cách nhấp chuột). –

+0

@BryanOakley Tôi không biết ý bạn là gì "gọi lại cho sự kiện <1>". Có vẻ như dự đoán của tôi là sai ... Dự đoán tiếp theo của tôi là bạn đề xuất ràng buộc nhấp chuột duy nhất trong tiện ích văn bản của tôi với một số chức năng gọi lại sẽ gọi ... txt.focus_set() Và có lẽ cũng làm như vậy và nhấp chuột ba lần (nếu tkinter có chưa kiểm tra)> Hiện tại, tôi chỉ có liên kết/gọi lại cho nhưng tất nhiên tôi có thể tạo một liên kết đặc biệt và gọi lại một dòng với focus_set(). Tôi sẽ thử và gửi nó cho "khách hàng Mac" của tôi để kiểm tra ... Cảm ơn một lần nữa. – Momus

+0

câu trả lời ban đầu của tôi cho biết "gán một ràng buộc cho để đặt tiêu điểm rõ ràng cho tiện ích văn bản bị tắt". Tôi nghĩ điều đó rõ ràng, nhưng rõ ràng là không. Tôi đã thêm một ví dụ để làm rõ. Ngoài ra, bạn không cần phải làm tương tự cho một nhấp chuột đôi hoặc ba lần, vì cách duy nhất để thực hiện nhấp đúp hoặc gấp ba lần là lần đầu tiên thực hiện một cú nhấp chuột, vì vậy giải pháp này sẽ cho phép bạn tăng gấp đôi hoặc nhấp ba lần để chọn từ và dòng, cũng như nhấp và kéo để chọn một vùng. –

2

Xin lỗi vì đã chạm một câu hỏi cũ, nhưng tôi cũng đang tìm kiếm câu trả lời cho câu hỏi này và cuối cùng đã tìm được giải pháp. Giải pháp tôi tìm thấy liên quan đến việc ghi đè các ràng buộc chính khi tiện ích văn bản đã tập trung và khá đơn giản. Đã tìm thấy here.

Để ghi đè lên các ràng buộc của một tiện ích có chức năng liên kết trong đó bạn chuyển một chuỗi nội dung sẽ bị ghi đè và hàm mới bạn muốn gọi.

self.txtBox.bind("<Key>", self.empty) 

Một nơi nào khác trong lớp bạn cần xác định hàm để xử lý sự kiện.

def empty(self, event): 
     return "break" 

Bằng cách trả về chuỗi "ngắt", trình xử lý sự kiện biết dừng sau chức năng của bạn, thay vì tiếp tục hành động mặc định.

Tôi hy vọng điều này sẽ trả lời câu hỏi của bạn. Chúc mừng.

Các vấn đề liên quan