自2天以来,我一直在尝试解决一个问题:
int main(int argc, char *argv[])
{
qputenv("QT_IM_MODULE", QByteArray("qtvirtualkeyboard"));
qputenv("QT_VIRTUALKEYBOARD_STYLE", QByteArray("MacoUV"));
QApplication app(argc, argv);
int result;
MacoUVController * pController = new MacoUVController();
pController->start();
std::cout << "MacoUV Controller thread: " << pController->thread() <<std::endl;
std::cout << "MacoUV Controller thread: " << qApp->instance()->thread() <<std::endl;
result = app.exec();
return result;
}
当我在控制台中显示 pController 和 qApp 线程时,显示了两个不同的线程地址,我不明白为什么,因为所有对象通常都是在主线程中创建的,除非您将它们明确地移动(例如,使用moveToThread)到另一个线程中。
PS:MacoUVController 不能从QThread继承,它只有一个QThread Object成员在代码中的某个位置用于移动另一个对象...
.h of MacoUVController:
class MacoUVController : public MAGenFwk::Controller
{
Q_OBJECT
public:
MacoUVController();
~MacoUVController();
bool isStateActive(int);
void setCurrentCmd(QString cmd);
QString currentCmd() const;
QString getTemperatureInfo();
QString getIlluminationInfo();
signals:
void sig_serialConnect(QString config);
void sig_closeMachine();
void sig_openMachine();
void sig_sendConfigInfo(QString infos);
void sig_shutdown();
void sig_microShutdown();
void sig_machineOpened(int machineState);
...
...
private:
int a_machineStatus;
QString a_currentCmd;
QThread a_commThread;
}
MacoUVController ctor
MacoUVController::MacoUVController() : MAGenFwk::Controller()
{
a_machineStatus = 0;
a_isConfigDone = false;
a_isConnected = false;
a_isShutdownRequested = false;
a_pModelManager = MAGenFwk::ModelManager::getInstance();
initModels();
a_pView = new MainView();
#ifdef SIMULATION
a_pSimuView = new SimulationView();
a_pSimuView->show();
#endif
LabelModel * pLabelModel = dynamic_cast<LabelModel *>(a_pModelManager->getModel("LabelModel"));
MAGenFwk::FileManagerModel * pFile = new MAGenFwk::FileManagerModel("stylesheet.txt", "");
connect(a_pView, SIGNAL(sig_dateChanged()), this, SLOT(slt_saveResetDailyInfo()));
connect(a_pParametersModel, SIGNAL(sig_fileChanged()), this, SLOT(slt_updateParameters()));
connect(a_pParametersModel, SIGNAL(sig_fileError()), this, SLOT(slt_setFileError()));
connect(a_pCountersModel, SIGNAL(sig_fileError()), this, SLOT(slt_setFileError()));
connect(a_pMasksModel, SIGNAL(sig_fileError()), this, SLOT(slt_setFileError()));
connect(a_pLoginModel, SIGNAL(sig_fileError()), this, SLOT(slt_setFileError()));
connect(pLabelModel, SIGNAL(sig_fileError()), this, SLOT(slt_setFileError()));
connect(pFile, SIGNAL(sig_fileError()), this, SLOT(slt_setFileError()));
a_pParametersModel->load();
a_pCountersModel->load();
a_pLoginModel->load();
a_pMasksModel->load();
pLabelModel->load();
pFile->load();
a_confingInfos = getIlluminationInfo() + getTemperatureInfo();
a_loginPopupFlag = false;
a_pAutoLogoutTimer = new QTimer(this);
a_shutDownTimer = nullptr;
if (a_pDiagManagementModel->isRestricted(EAR_APP))
{
a_pView->slt_changeBackground(EAB_ERROR);
return;
}
QFile f(pFile->getFilePath());
f.open(QIODevice::ReadOnly);
qApp->setStyleSheet(f.readAll().data());
connect(a_pCountersModel, SIGNAL(sig_counterIncremented(QString)), this, SLOT(slt_updateCounter(QString)));
connect(a_pView, SIGNAL(sig_usbDriveEvent(QString, bool)), a_pDataManagementModel, SLOT(slt_setUsbDrive(QString, bool)));
connect(a_pView, SIGNAL(sig_close()), this, SLOT(slt_cleanUp()));
//std::cout << "Controller thread: " << this->thread() << std::endl;
}
从Controller继承的MacoUVController的启动方法
void Controller::start()
{
if (a_isStarted == false)
{
_createStateMachine();
_createBehaviors();
_createTransitions();
a_pStateMachine->start();
EngeneerLog::getInstance();
_start();
a_isStarted = true;
}
}
控制器.h:
class QStateMachine;
namespace MAGenFwk
{
class Plugin;
class ModelManager;
class Controller : public QObject
{
Q_OBJECT
public:
explicit Controller(QObject *parent = 0);
~Controller();
void start();
signals:
void sig_logout();
private slots:
protected:
QStateMachine * a_pStateMachine;
ModelManager * a_pModelManager;
private:
virtual void _createStateMachine() = 0;
virtual void _createTransitions() = 0;
virtual void _createBehaviors() = 0;
virtual void _start();
bool a_isStarted;
};
} // end namespace MAGenFwk
#endif
在代码中的某个地方,我通过移动MachineModel使用QThread对象:
a_pMachineModel->moveToThread(&a_commThread);
a_commThread.start();
这是MachineModel的.h:
class MacoUVMachineModel : public MAGenFwk::MachineModel
{
Q_OBJECT
public:
MacoUVMachineModel();
~MacoUVMachineModel();
void manageSpecificMachineStatus(const QString & machineStatus);
void openMachine();
void closeMachine();
void executeMachineOperation(EMachineOp operationType);
bool isBusy();
bool isActive(EMachineState machineState);
bool sendConfigInfo(QString parameters);
bool startCycle();
bool stopCycle();
bool startAutotests();
bool shutDown();
bool getVersion(QString & version);
MachineData * getMachineData();
signals:
void sig_machineBusyStateChanged(bool isBusy);
void sig_machineStateChanged(int stateMask);
void sig_updateSampleInfos(MachineSample * pSample);
void sig_machineOperationInProgress(const QString & operation = QString());
void sig_isConnected(bool serialConnect, bool configDone);
void sig_cmdExecResult(bool, void*);
void sig_getConfigInfos();
void sig_getVersion(QString);
/**
* @brief sig_setMachineOp
* @param mop
* this signal is created to avoid accessing the GenericPopupModel in MachineModel
* because then we'll access in two differents thread without any lock, to prevent
* unpredictable issues, we access the GenericPopupModel in the HMI Thread
*/
void sig_setMachineOp(EMachineOp mop);
public slots:
void slt_verifyOperationSuccess();
void slt_setFailureMessage();
void slt_serialConnect(QString config);
void slt_closeMachine();
void slt_openMachine();
void slt_startCycle();
void slt_stopCycle();
void slt_initAutotests();
void slt_sendConfigInfo(QString);
void slt_shutdown();
void slt_threadFinished();
protected:
void globalInit();
void terminate();
private slots:
void slt_restablishComm();
private:
void setBusyState(bool isBusy);
void setMachineState(int stateMask);
void _initSpecificMachineErrors() {}
void _initSpecificMachineWarnings() {}
QString getConfigInfo();
QString getAgitationInfo();
QString getIlluminationInfo();
QString getTemperatureInfo();
bool a_isBusy;
int a_lastState;
int a_machineState;
MachineData * a_pMachineData;
QTimer * a_pOperationTimer;
QString a_operationCmd;
GenericPopupModel * a_pPopupModel;
//MAGenFwk::ParametersModel * a_pParametersModel;
DiagManagementModel * a_pDiagManagementModel;
};
#endif // MACHINEMODEL_H
我使用另一个线程的唯一地方是在Machine对象中移动MachineModel对象,该对象是MacoUVController类的成员。所以对我来说,没有必要让MacoUVController位于不同的线程中,它应该位于主线程中,而只有MachineModel应该位于另一个线程中...也许我弄错了...
Env: -Windows 10 64位(最近升级到1803版本) -基于QT 5.11的Qt Creator 4.7,但我使用的是Qt 5.7,这可能是个问题吗? -编译器:mingw5.3.0 C ++ 32位
有关此问题的任何解释吗?