de-vraag
  • Pertanyaan
  • Tag
  • Pengguna
Notifikasi
Imbalan
Registrasi
Setelah Anda mendaftar, Anda akan diberitahu tentang balasan dan komentar untuk pertanyaan Anda.
Gabung
Jika Anda sudah memiliki akun, masuk untuk memeriksa pemberitahuan baru.
Akan ada hadiah untuk pertanyaan, jawaban, dan komentar tambahan.
Lebih
Sumber
Sunting
 Addy
Addy
Question

Qt Slot dan C++11 lambda

Saya memiliki QAction item yang saya menginisialisasi seperti berikut:

QAction* action = foo->addAction(tr("Some Action"));
connect(action, SIGNAL(triggered()), this, SLOT(onSomeAction()));

Dan kemudian onSomeAction mirip seperti:

void MyClass::onSomeAction()
{
    QAction* caller = qobject_cast<QAction*>(sender());
    Q_ASSERT(caller != nullptr);

    // do some stuff with caller
}

Ini bekerja baik-baik saja, saya mendapatkan pemanggil kembali benda dan I'm dapat menggunakannya seperti yang diharapkan. Kemudian saya mencoba C++11 cara untuk menghubungkan objek seperti:

connect(action, &QAction::triggered, [this]()
{
    QAction* caller = qobject_cast<QAction*>(sender());
    Q_ASSERT(caller != nullptr);

    // do some stuff with caller
});

Tapi pemanggil adalah selalu nol dan dengan demikian Q_ASSERT pemicu. Bagaimana saya bisa menggunakan lambdas untuk mendapatkan pengirim?

48 2013-11-01T01:21:49+00:00 3
Reinstate Monica
Reinstate Monica
Pertanyaan edit 1 November 2013 в 8:55
Pemrograman
c++
qt
c++11
Solution / Answer
Reinstate Monica
Reinstate Monica
1 November 2013 в 5:08
2013-11-01T05:08:46+00:00
Lebih
Sumber
Sunting
#22683922

Jawaban yang sederhana adalah: anda dapat't. Atau, lebih tepatnya, anda don't ingin (atau perlu!) untuk menggunakan pengirim(). Hanya menangkap dan menggunakan action.

//                                Important!
//                                   vvvv
connect(action, &QAction::triggered, this, [action, this]() {
    // use action as you wish
    ...
});

Spesifikasi ini sebagai objek konteks untuk functor memastikan bahwa functor tidak akan dipanggil jika salah tindakan atau ini (a QObject) tidak ada lagi. Jika tidak, functor akan mencoba untuk referensi dangling pointer.

Secara umum, berikut ini harus terus ketika menangkap konteks variabel untuk sebuah functor berlalu untuk connect, dalam rangka untuk menghindari penggunaan dangling pointer/referensi:

  1. Pointer ke sumber dan target objek connect dapat ditangkap oleh nilai, seperti di atas. Itu dijamin bahwa jika functor dipanggil, kedua ujung koneksi yang ada.

menghubungkan(a, &A::foo, b, [a, b]{});

Skenario di mana a dan b berada di benang yang berbeda memerlukan perhatian khusus. Hal ini tidak dapat dijamin bahwa setelah functor dimasukkan, beberapa benang tidak akan menghapus objek.

Itu adalah ungkapan bahwa sebuah objek hanya hancur dalam thread(), atau di thread apapun jika benang() == nullptr. Sejak thread's acara loop memanggil functor, null thread ini pernah ada masalah selama b - tanpa benang functor won't akan dipanggil. Sayangnya, ada's tidak ada jaminan tentang masa a b's benang. Hal ini dengan demikian lebih aman untuk menangkap diperlukan negara dari tindakan dengan nilai sebaliknya, sehingga a's seumur hidup tidak perhatian.

// AMAN auto anama = a->objectName(); menghubungkan(a, &A::foo, b, [nama, b]{ qDebug() << nama; }); // Tidak AMAN menghubungkan(a, &A::foo, b, [a,b]{ qDebug() << a>objectName(); });

  1. Baku pointer ke objek lain dapat ditangkap oleh nilai jika anda're benar-benar yakin bahwa seumur hidup dari benda-benda yang mereka arahkan ke tumpang tindih seumur hidup dari sambungan.

statis C c; auto p = &c; menghubungkan(..., [p]{});

  1. Ditto untuk referensi ke objek:

statis D d; menghubungkan(..., [&d]{});

  1. Non-copyable benda-benda yang don't berasal dari QObject harus ditangkap melalui mereka bersama pointer dengan nilai.

std::shared_ptr e { E }; QSharedPointer f { F baru; } menghubungkan(..., [e,f]{});

  1. QObject tinggal di thread yang sama dapat ditangkap olehQPointer`; nilainya harus diperiksa sebelum digunakan dalam functor.

QPointer g { this->orang tua(); } menghubungkan(..., [g]{ jika (g) ... });

  1. `QObject tinggal di thread lain harus ditangkap oleh ruang pointer atau lemah pointer. Orang tua mereka harus diset sebelum kehancuran mereka, jika tidak, anda'll memiliki double menghapus:

kelas I : umum QObject { ... ~Saya() { setParent(nullptr); } };

std::shared_ptr i { I }; menghubungkan(..., [i]{ ... });

std::weak_ptr j { aku }; menghubungkan(..., [j]{ auto jp = j.kunci(); jika (jp) { ... } });

Reinstate Monica
Reinstate Monica
Jawaban edit 12 September 2015 в 3:08
74
0
 MiB_Coder
MiB_Coder
22 Januari 2017 в 1:20
2017-01-22T13:20:49+00:00
Lebih
Sumber
Sunting
#22683923

Menggunakan lambdas sebagai slot adalah langsung (misalnya untuk sebuah acara dari QSpinbox):

connect(spinboxObject, &QSpinBox::editingFinished, this, [this]() {<do something>});

Tapi ini hanya bekerja jika sinyal tidak kelebihan beban (yang berarti ada beberapa sinyal dengan nama yang sama tetapi berbeda argumen).

connect(spinboxObject, &QSpinBox::valueChange, this, [this]() {<do something>});

memberikan mengkompilasi kesalahan, karena tidak ada dua kelebihan beban sinyal: valueChanged(int) dan valueChanged(const QString&) Jadi itu perlu untuk memenuhi syarat versi mana yang harus digunakan:

connect(spinboxObject, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), this, [this](int newValue){ });

Sedikit lebih pendek (atau lebih baik dibaca) adalah penggunaan QOverload:

connect(spinboxObject, QOverload<int>::of(&QSpinBox::valueChanged), this, [this](int newValue) { });
12
0
Nikolay Khilyuk
Nikolay Khilyuk
24 September 2019 в 11:49
2019-09-24T11:49:49+00:00
Lebih
Sumber
Sunting
#22683925

Tanpa "" konteks, misalnya dari main():

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QLabel lbl{"Hello World!"};
    QPushButton btn;
    btn.show();
    lbl.show();

    QObject::connect(&btn, &QPushButton::clicked, [&lbl](){lbl.setText("Button clicked");});

    return a.exec();
}
0
0
Tambahkan pertanyaan
Kategori
Semua
Teknologi
Budaya / Rekreasi
Kehidupan / Seni
Ilmu Pengetahuan
Profesional
Bisnis
Pengguna
Semua
Baru
Populer
1
Галина Утяшова
Terdaftar 19 jam yang lalu
2
Asilbek Qadamboyev
Terdaftar 3 hari yang lalu
3
Akshit Mehta
Terdaftar 6 hari yang lalu
4
me you
Terdaftar 1 minggu yang lalu
5
Никита иванов
Terdaftar 1 minggu yang lalu
ID
KO
RU
© de-vraag 2022
Sumber
stackoverflow.com
di bawah lisensi cc by-sa 3.0 dengan atribusi