2009-07-20 3 views
3

Я хотел бы знать, какое из следующего является правильным способом делать вещи с сигналом/слотом в Qt.Сигнал Qt в слот специального объекта

Мне нужен способ иметь несколько экземпляров диалогового окна, то есть: A и B. И мне нужно сообщить A для печати «A» и B для печати «B» из другой темы. Поэтому я считаю, мне нужно что-то вроде как:

ВАРИАНТ 1)A->print("A") и B->print("B")

или лучше сделать:

ВАРИАНТ 2)emit print("A") и emit print("B") и использовать способ, который я не знаю, только A поймать «А» и только B поймать «В».

я получил вариант 1 работает следующим образом:

class myClass : public QMainWindow 
{ 
    Q_OBJECT 

public: 
    myClass (QWidget *parent = 0, Qt::WFlags flags = 0); 
    ~myClass(); 
    void doPrint(char* text) 
    { 
     emit mySignal(text); 
    } 
private: 
    Ui::myClass ui; 

public slots: 
    void newLog(char* msg); 

signals: 
    void mySignal(char* msg); 
}; 

myClass::myClass(QWidget *parent, Qt::WFlags flags) : QMainWindow(parent, flags) 
{ 
    ui.setupUi(this); 
    connect(this, SIGNAL(mySignal(char*)), this, SLOT(newLog(char*))); 
} 

void myClass::newLog(char* msg) 
{ 
    ui.textEdit->append(msg); 
} 

, а затем все, что нужно сделать, это:

myClass* instanceA = new myClass(); 
myClass* instanceB = new myClass(); 
instanceA->doPrint("A"); 
instanceB->doPrint("B"); 

это право?

Спасибо!

+0

Давайте переходите с противоположной стороны вашего вопроса. В этом случае вы можете чувствовать себя комфортно с вариантом 2?Можете сказать пример, когда второй случай имеет преимущество, если единственное, что вы хотите, это напечатать «A» и «B»? – Narek

ответ

1

В этом упрощенном примере я думаю, что вы находитесь на правильном пути с вариантом 1. Однако было бы еще лучше, если бы вам не нужен метод doPrint(), который также устранил бы необходимость в сигнале mySignal (при наименее в myClass). Вместо этого, я хотел бы предложить унаследовать ваши темы от QThread, если не уже, а делать что-то вроде этого:

class myThread : public QThread 
{ 
    Q_OBJECT 

public: 
    myThread (QWidget *parent = 0) : QThread(parent) {} 
    ~myThread() {} 
    void run(char* text) 
    { 
     emit mySignal(text); 
    } 

signals: 
    void mySignal(char* msg); 
}; 

Тогда вам нужно сделать что-то вроде этого:

myClass* instanceA = new myClass(); 
myThread* threadA = new myThread(); 
connect(threadA, SIGNAL(mySignal(char*)), instanceA, SLOT(newLog(char*)), Qt::QueuedConnection); 
threadA->run("A"); 

Очевидно, что в большинстве non-example code, вы не должны передавать строку в run, а скорее генерируете строки, которые должны быть запущены, как работает threadA. Преимущество состоит в том, что это устраняет проблемы потоков из myClass, и вам нужно только подумать о них, где они связаны. С другой стороны, вы вводите меньшее количество зависимостей в потоки, так как им не нужно знать о myClass, чтобы иметь возможность регистрироваться.

+1

Пожалуйста, прекратите распространять эту дезинформацию о Qt :: QueuedConnection, которая требуется в этом случае. Это больше не для последних трех версий Qt. –

+1

@mmutz, я сделал это в своем примере, чтобы обеспечить тип соединения, основанный на http://doc.trolltech.com/4.5/threads.html#signals-and-slots-across-threads, который частично указывает на «QThread» объекты живут в потоке, где был создан объект, а не в потоке, который создается при вызове QThread :: run(). Обычно небезопасно предоставлять слоты в вашем подклассе QThread. " Однако теперь я вижу, что «вы можете безопасно испускать сигналы из вашей реализации QThread :: run() ...», которые я ранее пропустил. Несмотря на это, указание типа подключения не наносит вреда тому, что я вижу. –

2

Поскольку ваш слот находится в другом потоке, вы должны использовать Meta-Object System для вызова метода асинхронно. Правильный способ сделать это - использовать QMetaObject::invokeMethod

НЕ подклассифицируйте QThread и переопределите метод запуска. Для получения дополнительной информации об этом см: http://blog.qt.digia.com/blog/2010/06/17/youre-doing-it-wrong/

void otherClass::printTo(myClass* instance, char* text) 
{ 
    QMetaObject::invokeMethod(instance,  // pointer to a QObject 
           "doPrint",  // member name (no parameters here) 
           Qt::QueuedConnection,  // connection type 
           Q_ARG(char*, text));  // parameters 
} 

void myClass::doPrint(char* text) 
{ 
    ui.textEdit->append(text); 
} 

myClass* instanceA = new myClass(); 
myClass* instanceB = new myClass(); 
printTo(instanceA, "A"); 
printTo(instanceB, "B"); 

Если тип символ * не был зарегистрирован в системе Meta-Object, сделайте это с Q_DECLARE_METATYPE(char*);

затем:

qRegisterMetaType<char*>("charPtr"); 
Смежные вопросы