Sự kiện Qt và tín hiệu / khe cắm


97

Trong thế giới Qt, sự khác biệt của sự kiện và tín hiệu / khe cắm là gì?

Có thay thế cái kia không? Các sự kiện có phải là sự trừu tượng của tín hiệu / khe cắm không?

Câu trả lời:


30

Các tài liệu Qt có thể giải thích nó tốt nhất:

Trong Qt, các sự kiện là các đối tượng, bắt nguồn từ QEventlớp trừu tượng , đại diện cho những thứ đã xảy ra bên trong một ứng dụng hoặc là kết quả của hoạt động bên ngoài mà ứng dụng cần biết. Các sự kiện có thể được nhận và xử lý bởi bất kỳ phiên bản nào của QObjectlớp con, nhưng chúng đặc biệt liên quan đến các widget. Tài liệu này mô tả cách các sự kiện được phân phối và xử lý trong một ứng dụng điển hình.

Vì vậy, sự kiện và tín hiệu / khe cắm là hai cơ chế song song thực hiện những việc giống nhau. Nói chung, một sự kiện sẽ được tạo bởi một thực thể bên ngoài (ví dụ: bàn phím hoặc con lăn chuột) và sẽ được phân phối thông qua vòng lặp sự kiện trong QApplication. Nói chung, trừ khi bạn thiết lập mã, bạn sẽ không tạo sự kiện. Bạn có thể lọc chúng qua QObject::installEventFilter()hoặc xử lý các sự kiện trong đối tượng phân lớp bằng cách ghi đè các hàm thích hợp.

Tín hiệu và Khe cắm dễ dàng tạo và nhận hơn nhiều và bạn có thể kết nối hai QObjectlớp con bất kỳ . Chúng được xử lý thông qua Metaclass (hãy xem tệp moc_classname.cpp của bạn để biết thêm), nhưng hầu hết giao tiếp giữa các lớp mà bạn sẽ tạo ra có thể sẽ sử dụng tín hiệu và khe cắm. Tín hiệu có thể được gửi ngay lập tức hoặc hoãn lại qua hàng đợi (nếu bạn đang sử dụng luồng).

Một tín hiệu có thể được tạo ra.


hàng đợi hoãn lại giống với vòng lặp sự kiện hàng đợi, hay nó tồn tại hai hàng đợi? một cho các tín hiệu bị nhiễu và bật cho sự kiện?
Guillaume07

29
@Raphael xấu hổ vì bạn đã chấp nhận câu trả lời này. - Đoạn trích dẫn thậm chí không có từ "tín hiệu" hoặc "khe cắm"!
Robert Siemer

1
@neuronet: đoạn văn được trích dẫn với "[nó] giải thích nó tốt nhất", mà nó không. Không có gì. Một chút cũng không.
Robert Siemer

@Robert, vậy nếu dòng giới thiệu nhỏ đó được thay đổi thành "Trước tiên, hãy xem xét cách tài liệu giải thích các sự kiện, trước khi chuyển sang xem xét chúng liên quan đến tín hiệu như thế nào", bạn có đồng ý với câu trả lời không? Nếu vậy, chúng tôi chỉ có thể chỉnh sửa câu trả lời để cải thiện nó vì đó là một điểm nhỏ và tôi đồng ý rằng có thể được diễn đạt tốt hơn. [Chỉnh sửa đó là một câu hỏi thực sự: vì tôi không chắc phần còn lại của nó tốt hơn nhiều .... nhưng chỉ vì phần được trích dẫn không đề cập đến các tín hiệu có vẻ là một sự lo lắng hời hợt nếu phần còn lại của nó thực sự tốt, mà tôi không giả định .]
eric

4
@neuronet, nếu bạn xóa hoàn toàn câu trích dẫn, nó sẽ cải thiện câu trả lời trong mắt tôi. - Nếu bạn loại bỏ toàn bộ câu trả lời, nó sẽ cải thiện toàn bộ QA này.
Robert Siemer

152

Trong Qt, cả tín hiệu và sự kiện đều là cách triển khai của mẫu Observer . Chúng được sử dụng trong các tình huống khác nhau vì chúng có những điểm mạnh và điểm yếu khác nhau.

Trước hết, chúng ta hãy xác định chính xác ý nghĩa của chúng tôi về 'sự kiện Qt': một hàm ảo trong lớp Qt, mà bạn dự kiến ​​sẽ thực hiện lại trong lớp cơ sở của mình nếu bạn muốn xử lý sự kiện. Nó liên quan đến mẫu Phương pháp Mẫu .

Lưu ý cách tôi đã sử dụng từ " xử lý ". Thật vậy, đây là sự khác biệt cơ bản giữa mục đích của tín hiệu và sự kiện:

  • Bạn " xử lý " các sự kiện
  • Bạn " nhận được thông báo về " phát xạ tín hiệu

Sự khác biệt là khi bạn "xử lý" sự kiện, bạn nhận trách nhiệm "đáp trả" bằng một hành vi có ích bên ngoài lớp học. Ví dụ: hãy xem xét một ứng dụng có một nút với một số trên đó. Ứng dụng cần cho phép người dùng tập trung vào nút và thay đổi số bằng cách nhấn các phím bàn phím "lên" và "xuống". Nếu không, nút sẽ hoạt động như bình thường QPushButton(nó có thể được nhấp vào, v.v.). Trong Qt, điều này được thực hiện bằng cách tạo một "thành phần" nhỏ có thể tái sử dụng của riêng bạn (lớp con của QPushButton), sẽ thực hiện lại QWidget::keyPressEvent. Mã giả:

class NumericButton extends QPushButton
    private void addToNumber(int value):
        // ...

    reimplement base.keyPressEvent(QKeyEvent event):
        if(event.key == up)
            this.addToNumber(1)
        else if(event.key == down)
            this.addToNumber(-1)
        else
            base.keyPressEvent(event)

Xem? Đoạn mã này trình bày một sự trừu tượng mới: một widget hoạt động giống như một nút, nhưng có thêm một số chức năng. Chúng tôi đã thêm chức năng này rất tiện lợi:

  • Kể từ khi chúng tôi thực hiện lại một ảo, việc triển khai của chúng tôi tự động được đóng gói trong lớp của chúng tôi. Nếu các nhà thiết kế của Qt đã tạo ra keyPressEventmột tín hiệu, chúng tôi sẽ cần quyết định xem sẽ kế thừa QPushButtonhay chỉ kết nối bên ngoài với tín hiệu. Nhưng điều đó sẽ thật ngu ngốc, vì trong Qt, bạn luôn phải kế thừa khi viết một widget với hành vi tùy chỉnh (vì lý do chính đáng - khả năng tái sử dụng / mô đun). Vì vậy, bằng cách tạo ra keyPressEventmột sự kiện, họ truyền đạt ý định của mình mà keyPressEventchỉ là một khối chức năng cơ bản. Nếu đó là một tín hiệu, nó sẽ trông giống như một thứ mà người dùng phải đối mặt, khi nó không được dự định.
  • Vì việc triển khai chức năng ở lớp cơ sở có sẵn, chúng tôi dễ dàng triển khai mô hình Chuỗi trách nhiệm bằng cách xử lý các trường hợp đặc biệt của chúng tôi (phím lên và xuống) và để phần còn lại cho lớp cơ sở. Bạn có thể thấy điều này sẽ gần như không thể nếu keyPressEventlà một tín hiệu.

Thiết kế của Qt đã được suy nghĩ kỹ lưỡng - chúng đã khiến chúng ta rơi vào hố sâu thành công bằng cách giúp bạn dễ dàng làm điều đúng và khó làm điều sai (bằng cách biến keyPressEvent thành một sự kiện).

Mặt khác, hãy xem xét cách sử dụng đơn giản nhất QPushButton- chỉ cần khởi tạo nó và nhận thông báo khi nó được nhấp vào :

button = new QPushButton(this)
connect(button, SIGNAL(clicked()), SLOT(sayHello())

Điều này rõ ràng được thực hiện bởi người dùng của lớp:

  • nếu chúng ta phải phân lớp QPushButtonmỗi khi chúng ta muốn nút nào đó thông báo cho chúng ta về một cú nhấp chuột, điều đó sẽ đòi hỏi rất nhiều lớp con mà không có lý do chính đáng! Một tiện ích luôn hiển thị "Xin chào thế giới" messageboxkhi được nhấp vào chỉ hữu ích trong một trường hợp duy nhất - vì vậy nó hoàn toàn không thể sử dụng lại được. Một lần nữa, chúng ta không có lựa chọn nào khác ngoài việc làm điều đúng đắn - bằng cách kết nối với nó từ bên ngoài.
  • chúng tôi có thể muốn kết nối nhiều khe cắm với clicked()- hoặc kết nối nhiều tín hiệu với sayHello(). Với tín hiệu không có ồn ào. Với phân lớp, bạn sẽ phải ngồi xuống và suy ngẫm về một số sơ đồ lớp cho đến khi bạn quyết định một thiết kế phù hợp.

Lưu ý rằng một trong những nơi QPushButtonphát ra clicked()đang được mousePressEvent()triển khai. Điều đó không có nghĩa là clicked()mousePressEvent()có thể thay thế cho nhau - chỉ là chúng có liên quan với nhau.

Vì vậy, các tín hiệu và sự kiện có những mục đích khác nhau (nhưng có liên quan ở chỗ cả hai đều cho phép bạn "đăng ký" nhận thông báo về điều gì đó đang xảy ra).


Tôi hiểu ý tưởng. Sự kiện là mỗi lớp, tất cả các cá thể của một lớp sẽ phản ứng giống nhau, tất cả chúng sẽ gọi cùng một QClassName :: event. Nhưng tín hiệu là trên từng đối tượng, mỗi đối tượng có thể có kết nối khe cắm tín hiệu duy nhất.
炸鱼 薯条 德里克

39

Tôi không thích câu trả lời cho đến nay. - Hãy để tôi tập trung vào phần này của câu hỏi:

Các sự kiện có phải là sự trừu tượng của tín hiệu / khe cắm không?

Câu trả lời ngắn gọn: không. Câu trả lời dài đặt ra một câu hỏi “tốt hơn”: Các tín hiệu và sự kiện liên quan với nhau như thế nào?

Một vòng lặp chính không hoạt động (ví dụ như Qt) thường bị "kẹt" trong lệnh gọi select () của hệ điều hành. Lệnh gọi đó làm cho ứng dụng "ngủ", trong khi nó chuyển một loạt các ổ cắm hoặc tệp hoặc bất cứ thứ gì đến hạt nhân yêu cầu: nếu có điều gì đó thay đổi trên những thứ này, hãy để lệnh gọi select () quay trở lại. - Và hạt nhân, với tư cách là chủ nhân của thế giới, biết khi nào điều đó xảy ra.

Kết quả của lệnh gọi select () đó có thể là: dữ liệu mới trên ổ cắm kết nối với X11, một gói tới cổng UDP mà chúng tôi lắng nghe được gửi đến, v.v. - Nội dung đó không phải là tín hiệu Qt, cũng không phải là sự kiện Qt và Vòng lặp chính Qt tự quyết định nếu nó biến dữ liệu mới thành cái này, cái kia hoặc bỏ qua nó.

Qt có thể gọi một (hoặc một số) phương thức như keyPressEvent (), biến nó thành một sự kiện Qt một cách hiệu quả. Hoặc Qt phát ra một tín hiệu, có tác dụng tra cứu tất cả các chức năng đã đăng ký cho tín hiệu đó và gọi chúng lần lượt.

Một sự khác biệt của hai khái niệm đó có thể nhìn thấy ở đây: một vị trí không có phiếu bầu về việc các vị trí khác đã đăng ký tín hiệu đó sẽ được gọi hay không. - Sự kiện giống như một chuỗi và trình xử lý sự kiện quyết định xem nó có làm gián đoạn chuỗi đó hay không. Về mặt này, các tín hiệu trông giống như một ngôi sao hoặc một cái cây.

Một sự kiện có thể kích hoạt hoặc hoàn toàn được biến thành một tín hiệu (chỉ phát ra một tín hiệu và không gọi “super ()”). Một tín hiệu có thể được chuyển thành một sự kiện (gọi một trình xử lý sự kiện).

Điều gì sẽ tóm tắt những gì phụ thuộc vào trường hợp: tín hiệu được nhấp () - tóm tắt các sự kiện của chuột (một nút đi xuống và lên lại mà không cần di chuyển quá nhiều). Các sự kiện bàn phím là sự trừu tượng từ các cấp thấp hơn (những thứ như 果 hoặc é là một số phím bấm trên hệ thống của tôi).

Có thể focusInEvent () là một ví dụ ngược lại: nó có thể sử dụng (và do đó trừu tượng) tín hiệu được click (), nhưng tôi không biết liệu nó có thực sự làm không.


4
Tôi thấy phần này: "một khe cắm không có phiếu bầu về việc các khe cắm khác đã đăng ký tín hiệu đó sẽ được gọi hay không" rất khai sáng cho sự khác biệt giữa tín hiệu và sự kiện. Tuy nhiên, tôi có một câu hỏi liên quan: Tin nhắn là gì và các tin nhắn liên quan đến tín hiệu và sự kiện như thế nào? (nếu chúng có liên quan). Các thông điệp có phải là một sự trừu tượng đối với các tín hiệu và sự kiện không? Chúng có thể được dùng để mô tả sự tương tác như vậy giữa QObjects (hoặc các đối tượng khác?)
user1284631

@axeoth: Trong Qt, không có cái gọi là "tin nhắn". Vâng, có một hộp tin nhắn, nhưng đó là về nó.
Phục hồi Monica

@KubaOber: Cảm ơn bạn. Ý tôi là "sự kiện".
user1284631

3
@axeoth: Vậy thì câu hỏi của bạn là vớ vẩn. Nó viết: "các sự kiện là gì và các sự kiện liên quan đến tín hiệu và sự kiện như thế nào".
Phục hồi Monica

@KubaOber: Tôi không nhớ bối cảnh một năm sau. Dù sao thì, có vẻ như tôi đã hỏi điều tương tự như OP: sự khác biệt giữa chúng tôi là gì, các sự kiện và cách các sự kiện liên quan đến tín hiệu và vị trí. Thực sự là trường hợp hồi đó là gì, IIRC, tôi đang tìm cách bọc các lớp tín hiệu Qt / hướng theo khe cắm trong một số loại lớp không phải Qt, vì vậy tôi đang xem xét một số cách để ra lệnh cho lớp đầu tiên từ bên trong lớp sau. Tôi tưởng tượng rằng tôi đang xem xét việc gửi các sự kiện cho chúng, vì điều đó có nghĩa là tôi chỉ phải bao gồm tiêu đề Qt và không buộc các lớp của tôi triển khai tín hiệu / khe cắm.
user1284631

16

Sự kiện được gửi đi bởi vòng lặp sự kiện. Mỗi chương trình GUI cần một vòng lặp sự kiện, bất kể bạn viết nó là Windows hay Linux, sử dụng Qt, Win32 hoặc bất kỳ thư viện GUI nào khác. Mỗi luồng có vòng lặp sự kiện riêng. Trong Qt, "Vòng lặp sự kiện GUI" (là vòng lặp chính của tất cả các ứng dụng Qt) bị ẩn, nhưng bạn bắt đầu nó gọi:

QApplication a(argc, argv);
return a.exec();

Tin nhắn HĐH và các ứng dụng khác gửi đến chương trình của bạn được gửi đi dưới dạng sự kiện.

Tín hiệu và khe là cơ chế Qt. Trong quá trình biên dịch bằng moc (trình biên dịch siêu đối tượng), chúng được thay đổi thành các hàm gọi lại.

Sự kiện nên có một người nhận, điều này sẽ gửi nó. Không ai khác sẽ nhận được sự kiện đó.

Tất cả các khe kết nối với tín hiệu phát ra sẽ được thực thi.

Bạn không nên nghĩ về Tín hiệu là sự kiện, vì như bạn có thể đọc trong tài liệu Qt:

Khi một tín hiệu được phát ra, các khe kết nối với nó thường được thực thi ngay lập tức, giống như một lệnh gọi hàm thông thường. Khi điều này xảy ra, cơ chế tín hiệu và vị trí hoàn toàn độc lập với bất kỳ vòng lặp sự kiện GUI nào.

Khi bạn gửi một sự kiện, nó phải đợi một thời gian cho đến khi vòng lặp sự kiện gửi tất cả các sự kiện đến trước đó. Do đó, việc thực thi mã sau khi gửi sự kiện hoặc tín hiệu là khác nhau. Mã sau khi gửi một sự kiện sẽ được chạy ngay lập tức. Với các cơ chế tín hiệu và khe cắm, nó phụ thuộc vào loại kết nối. Thông thường, nó sẽ được thực thi sau tất cả các vị trí. Sử dụng Qt :: QueuedConnection, nó sẽ được thực thi ngay lập tức, giống như các sự kiện. Kiểm tra tất cả các loại kết nối trong tài liệu Qt .


Câu này cho tôi hiểu ngắn gọn về sự khác nhau giữa khe tín hiệu Qt và các sự kiện:When you send an event, it must wait for time when event loop dispatch all events that came earlier. Because of this, execution of the cod after sending event or signal is different
swdev

7

Có một bài báo thảo luận chi tiết về xử lý sự kiện: http://www.packtpub.com/article/events-and-signals

Nó thảo luận về sự khác biệt giữa các sự kiện và tín hiệu ở đây:

Sự kiện và tín hiệu là hai cơ chế song song được sử dụng để thực hiện cùng một việc. Như một sự khác biệt chung, các tín hiệu hữu ích khi sử dụng tiện ích con, trong khi các sự kiện hữu ích khi triển khai tiện ích con. Ví dụ: khi chúng tôi đang sử dụng một tiện ích con như QPushButton, chúng tôi quan tâm đến tín hiệu được nhấp () của nó hơn là các sự kiện nhấn chuột hoặc nhấn phím ở mức độ thấp khiến tín hiệu được phát ra. Nhưng nếu chúng ta đang triển khai lớp QPushButton, chúng ta quan tâm nhiều hơn đến việc triển khai mã cho các sự kiện chuột và phím. Ngoài ra, chúng tôi thường xử lý các sự kiện nhưng nhận được thông báo bằng cách phát tín hiệu.

Đây dường như là một cách nói phổ biến về nó, vì câu trả lời được chấp nhận sử dụng một số cụm từ giống nhau.


Lưu ý, vui lòng xem các bình luận hữu ích bên dưới về câu trả lời này của Kuba Ober, điều này khiến tôi tự hỏi liệu nó có thể hơi đơn giản không.


Tôi không thể hiểu chúng là hai cơ chế được sử dụng để hoàn thành cùng một việc như thế nào - Tôi nghĩ rằng đó là một sự tổng quát hóa vô ích không giúp ích cho ai cả.
Phục hồi Monica

@KubaOber không nó giúp tránh các chi tiết cấp thấp hơn. Bạn sẽ nói Python không hữu ích vì bạn có thể làm điều tương tự khi viết mã máy? :)
eric

2
Tôi đang nói rằng câu đầu tiên của trích dẫn là khái quát quá mức là vô ích. Về mặt kỹ thuật, điều đó không sai, nhưng chỉ vì bạn có thể, nếu bạn muốn như vậy, sử dụng chuyển sự kiện để thực hiện những gì cơ chế khe tín hiệu thực hiện và ngược lại. Nó sẽ rất cồng kềnh. Vì vậy, không, các khe tín hiệu không giống như các sự kiện, chúng không hoàn thành cùng một điều, và thực tế là cả hai đều tồn tại là rất quan trọng đối với sự thành công của Qt. Ví dụ về nút được trích dẫn hoàn toàn bỏ qua chức năng chung của hệ thống khe cắm tín hiệu.
Phục hồi Monica

1
"Sự kiện và tín hiệu là hai cơ chế song song được sử dụng để thực hiện cùng một việc trong phạm vi hẹp của một số tiện ích / điều khiển giao diện người dùng ." Phần in đậm bị thiếu nghiêm trọng và làm cho câu trích dẫn trở nên vô ích. Thậm chí sau đó, người ta có thể đặt câu hỏi rằng "điều tương tự" đã thực sự được hoàn thành đến mức nào: các tín hiệu cho phép bạn phản ứng với các sự kiện nhấp chuột mà không cần cài đặt bộ lọc sự kiện trên tiện ích (hoặc lấy từ tiện ích con). Làm điều đó mà không có tín hiệu sẽ phức tạp hơn nhiều và kết hợp chặt chẽ mã khách hàng với sự kiểm soát. Đó là thiết kế tồi.
Phục hồi Monica

1
Sự kiện là một khái niệm phổ biến . Việc thực hiện đặc biệt trong Qt cụ thể đặt chúng như cấu trúc dữ liệu truyền cho event. Cụ thể, các tín hiệu và khe cắm là các phương thức, trong khi cơ chế kết nối là một cấu trúc dữ liệu cho phép tín hiệu gọi một hoặc nhiều khe cắm được liệt kê là kết nối với nó. Tôi hy vọng bạn thấy rằng việc nói về tín hiệu / khe cắm như một số "tập hợp con" hoặc "biến thể" của các sự kiện là vô nghĩa và ngược lại. Họ thực sự là những thứ khác nhau mà xảy ra được sử dụng để kết thúc tương tự trong bối cảnh của một số vật dụng. Đó là nó. Bạn càng khái quát hóa, bạn càng trở thành IMHO ít hữu ích hơn.
Phục hồi Monica

5

TL; DR: Tín hiệu và khe cắm là các cuộc gọi phương thức gián tiếp. Sự kiện là cấu trúc dữ liệu. Vì vậy, chúng là những động vật khá khác biệt.

Thời điểm duy nhất khi chúng kết hợp với nhau là khi các cuộc gọi vị trí được thực hiện qua các ranh giới luồng. Các đối số lệnh gọi vị trí được đóng gói trong một cấu trúc dữ liệu và được gửi dưới dạng một sự kiện đến hàng đợi sự kiện của luồng nhận. Trong luồng nhận, QObject::eventphương thức giải nén các đối số, thực hiện lệnh gọi và có thể trả về kết quả nếu đó là một kết nối chặn.

Nếu chúng ta sẵn sàng khái quát hóa thành sự lãng quên, người ta có thể coi các sự kiện như một cách gọi eventphương thức của đối tượng đích . Đây là một cách gọi phương pháp gián tiếp, theo mốt - nhưng tôi không nghĩ đó là một cách nghĩ hữu ích về nó, ngay cả khi đó là một câu nói đúng.


2

Các sự kiện (theo nghĩa chung là tương tác giữa người dùng / mạng) thường được xử lý trong Qt với các tín hiệu / khe cắm, nhưng tín hiệu / khe cắm có thể thực hiện nhiều việc khác.

QEvent và các lớp con của nó về cơ bản chỉ là các gói dữ liệu được chuẩn hóa nhỏ để khung giao tiếp với mã của bạn. Nếu bạn muốn chú ý đến con chuột theo một cách nào đó, bạn chỉ cần nhìn vào API QMouseEvent và các nhà thiết kế thư viện không phải phát minh lại bánh xe mỗi khi bạn cần tìm ra con chuột đã làm gì ở một số góc của API Qt.

Đúng là nếu bạn đang chờ đợi các sự kiện (một lần nữa trong trường hợp chung) thuộc một loại nào đó, thì vị trí của bạn gần như chắc chắn sẽ chấp nhận một lớp con QEvent làm đối số.

Như đã nói, các tín hiệu và khe cắm chắc chắn có thể được sử dụng mà không cần QEvents, mặc dù bạn sẽ thấy rằng động lực ban đầu để kích hoạt tín hiệu thường sẽ là một số loại tương tác của người dùng hoặc hoạt động không đồng bộ khác. Tuy nhiên, đôi khi, mã của bạn sẽ đạt đến điểm mà việc kích hoạt một tín hiệu nhất định sẽ là điều đúng đắn cần làm. Ví dụ: kích hoạt tín hiệu được kết nối với thanh tiến trình trong một quá trình dài không liên quan đến QEvent cho đến thời điểm đó.


2
"Các sự kiện thường được xử lý trong Qt với các tín hiệu / khe cắm" - thực sự là không ... Các đối tượng QEvent luôn được truyền xung quanh thông qua các hình ảnh ảo quá tải! Ví dụ: không có tín hiệu "keyDown" trong QWidget - thay vào đó, keyDown là một hàm ảo.
Stefan Monov

Đồng ý với stefan, thực sự là một mảnh khá khó hiểu của Qt
Harald Scheirich

1
@Stefan: Tôi sẽ tranh luận rằng có ít ứng dụng Qt ghi đè keyDown (và thay vào đó chủ yếu sử dụng các tín hiệu như QAbstractButton :: đã nhấp và QLineEdit :: chỉnh sửa hoàn tất) để biện minh cho "thông thường". Tôi chắc chắn đã từng nhập liệu bằng bàn phím trước đây, nhưng đó không phải là cách xử lý sự kiện thông thường.
jkerian

sau khi bạn chỉnh sửa (làm rõ ý của bạn là "sự kiện"), bài đăng của bạn bây giờ là chính xác. Mặc dù vậy, tôi không sử dụng lại những từ như thế. Mọi thứ đủ lầy lội nếu không có tín hiệu gọi là "một loại sự kiện".
Stefan Monov

2

Tôi tìm thấy câu hỏi này khi đọc 'Xử lý sự kiện' của Leow Wee Kheng. Nó cũng nói:

nhập mô tả hình ảnh ở đây

Jasmine Blanchette nói:

Lý do chính khiến bạn sử dụng các sự kiện thay vì các lệnh gọi hàm tiêu chuẩn, hoặc các tín hiệu và vị trí, là các sự kiện có thể được sử dụng đồng bộ và không đồng bộ (tùy thuộc vào việc bạn gọi sendEvent () hay postEvents ()), trong khi gọi một hàm hoặc gọi một khe luôn đồng bộ. Một ưu điểm khác của các sự kiện là chúng có thể được lọc.


1

Một xem xét thực dụng nhỏ khác: phát hoặc nhận tín hiệu yêu cầu kế thừa QObjecttrong khi một đối tượng của bất kỳ kế thừa nào có thể đăng hoặc gửi một sự kiện (vì bạn gọi QCoreApplication.sendEvent()hoặc postEvent()) Đây thường không phải là vấn đề nhưng: để sử dụng tín hiệu, PyQt yêu cầu QObjectphải là siêu lớp đầu tiên, và bạn có thể không muốn sắp xếp lại thứ tự kế thừa của mình chỉ để có thể gửi tín hiệu.)


-1

Theo tôi, các sự kiện là hoàn toàn dư thừa và có thể bị loại bỏ. Không có lý do gì không thể thay thế tín hiệu bằng sự kiện hoặc sự kiện bằng tín hiệu, ngoại trừ Qt đã được thiết lập như nó vốn có. Các tín hiệu đã xếp hàng được bao bọc bởi các sự kiện và các sự kiện có thể được bao bọc bởi các tín hiệu, ví dụ:

connect(this, &MyItem::mouseMove, [this](QMouseEvent*){});

Sẽ thay thế mouseMoveEvent()chức năng tiện lợi được tìm thấy trong QWidget(nhưng không QQuickItemcòn trong nữa) và sẽ xử lý các mouseMovetín hiệu mà trình quản lý cảnh sẽ phát ra cho mục đó. Thực tế là tín hiệu được phát ra thay mặt cho vật phẩm bởi một số thực thể bên ngoài là không quan trọng và xảy ra khá thường xuyên trong thế giới của các thành phần Qt, mặc dù nó được cho là không được phép (các thành phần Qt thường phá vỡ quy tắc này). Nhưng Qt là một tập đoàn có nhiều quyết định thiết kế khác nhau và bị vùi dập khá nhiều vì sợ phá vỡ mã cũ (dù sao điều này cũng thường xuyên xảy ra).


Các sự kiện có lợi thế là tuyên truyền QObjectphân cấp cha mẹ-con, khi cần thiết. Kết nối tín hiệu / khe cắm chỉ là một lời hứa để gọi một chức năng, trực tiếp hoặc gián tiếp, khi một điều kiện nhất định được đáp ứng. Không có hệ thống phân cấp xử lý liên quan với các tín hiệu và vị trí.
ẩn danh

Bạn có thể thực hiện các quy tắc lan truyền tương tự với các tín hiệu. Không có quy tắc. rằng một tín hiệu nhất định không thể được cấp lại cho đối tượng khác (con). Bạn có thể thêm một acceptedtham số tham chiếu vào một tín hiệu và các vị trí xử lý tín hiệu đó hoặc bạn có thể có một cấu trúc làm tham số tham chiếu với một acceptedtrường. Nhưng Qt đã thực hiện các lựa chọn thiết kế mà nó đã đưa ra và chúng hiện đã được hoàn thiện.
user1095108

1
Về cơ bản, bạn chỉ đang thực hiện lại các sự kiện nếu bạn làm theo cách bạn đề xuất.
Fabio A.

@FabioA. Đó là điểm câu hỏi của OP. Sự kiện và tín hiệu có thể thay thế nhau.
user1095108

Nếu các sự kiện thực hiện lại của bạn, thì bạn không thay thế các sự kiện. Hơn thế nữa: các tín hiệu được triển khai trên đầu các sự kiện. Bạn cần một "hệ thống sự kiện" để nói với một số vòng lặp sự kiện khác, có thể trong một chuỗi không phải của bạn, rằng đôi khi trong tương lai nó phải thực thi một chức năng nhất định ở đâu đó.
Fabio A.
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.