GUI + c++ (switch case)

Du bist neu in der Welt von C++? Dann schau hier herein!
Antworten
puppetClon
Beiträge: 16
Registriert: 30. Oktober 2014 18:53

GUI + c++ (switch case)

Beitrag von puppetClon »

Guten Tag,

ich bräuchte mal eure Hilfe, und zwar steuere ich einen Schrittmotor via C++ an, d.h. momentan läuft die Auswahl ob der Motor links oder nach rechts läuft über die Console ab.
Siehe Code...simple switch case Funktion.

Der Professor kam nun kurz vor knapp an und möchte eine GUI haben via Qt. So weit so gut, meine Frage ist jetzt, kann ich bei QPushButton es ermöglichen, das bei einem Klick auf den jeweiligen Button
ein bestimmter Case aus meinem C++ Programm ausgeführt wird`?

Beispiel:
Button (Rechtslauf) anklicken -> Case 1 ausführen.

Code: Alles auswählen

#include "stdafx.h"

#define TMCL_ROR 1
#define TMCL_ROL 2
#define TMCL_MST 3
#define TMCL_MVP 4
#define TMCL_SAP 5
#define TMCL_GAP 6
#define TMCL_STAP 7
#define TMCL_RSAP 8
#define TMCL_SGP 9
#define TMCL_GGP 10
#define TMCL_STGP 11
#define TMCL_RSGP 12
#define TMCL_RFS 13
#define TMCL_SIO 14
#define TMCL_GIO 15
#define TMCL_SCO 30
#define TMCL_GCO 31
#define TMCL_CCO 32

#define TMCL_APPL_STOP 128
#define TMCL_APPL_RUN 129
#define TMCL_APPL_RESET 131

#define MVP_ABS 0
#define MVP_REL 1
#define MVP_COORD 2

#define RFS_START 0
#define RFS_STOP 1
#define RFS_STATUS 2

#define FALSE 0
#define TRUE 1

#define TMCL_RESULT_OK 0
#define TMCL_RESULT_NOT_READY 1
#define TMCL_RESULT_CHECKSUM_ERROR 2

//Usage: ComHandle=OpenRS232("COM5", CBR_9600)
HANDLE OpenRS232(const char* ComName, DWORD BaudRate)
{
HANDLE ComHandle;
DCB CommDCB;
COMMTIMEOUTS CommTimeouts;

ComHandle=CreateFile(ComName, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if(GetLastError()!=ERROR_SUCCESS) return INVALID_HANDLE_VALUE;
else
{
GetCommState(ComHandle, &CommDCB);

CommDCB.BaudRate=BaudRate;
CommDCB.Parity=NOPARITY;
CommDCB.StopBits=ONESTOPBIT;
CommDCB.ByteSize=8;

CommDCB.fBinary=1; //Binary Mode only
CommDCB.fParity=0;
CommDCB.fOutxCtsFlow=0;
CommDCB.fOutxDsrFlow=0;
CommDCB.fDtrControl=0;
CommDCB.fDsrSensitivity=0;
CommDCB.fTXContinueOnXoff=0;
CommDCB.fOutX=0;
CommDCB.fInX=0;
CommDCB.fErrorChar=0;
CommDCB.fNull=0;
CommDCB.fRtsControl=RTS_CONTROL_TOGGLE;
CommDCB.fAbortOnError=0;

SetCommState(ComHandle, &CommDCB);

//Set buffer size
SetupComm(ComHandle, 100, 100);

//Set up timeout values (very important, as otherwise the program will be very slow)
GetCommTimeouts(ComHandle, &CommTimeouts);

CommTimeouts.ReadIntervalTimeout=MAXDWORD;
CommTimeouts.ReadTotalTimeoutMultiplier=0;
CommTimeouts.ReadTotalTimeoutConstant=0;

SetCommTimeouts(ComHandle, &CommTimeouts);

return ComHandle;
}
}


//Usage: CloseRS232(ComHandle);
void CloseRS232(HANDLE Handle)
{
CloseHandle(Handle);
}


void SendCmd(HANDLE Handle, UCHAR Address, UCHAR Command, UCHAR Type, UCHAR Motor, INT Value)
{
UCHAR TxBuffer[9];
DWORD BytesWritten;
int i;

TxBuffer[0]=Address;
TxBuffer[1]=Command;
TxBuffer[2]=Type;
TxBuffer[3]=Motor;
TxBuffer[4]=Value >> 24;
TxBuffer[5]=Value >> 16;
TxBuffer[6]=Value >> 8;
TxBuffer[7]=Value & 0xff;
TxBuffer[8]=0;
for(i=0; i<8; i++)
TxBuffer[8]+=TxBuffer[i];

//Send the datagram
WriteFile(Handle, TxBuffer, 9, &BytesWritten, NULL);
}


UCHAR GetResult(HANDLE Handle, UCHAR *Address, UCHAR *Status, int *Value)
{
UCHAR RxBuffer[9], Checksum;
DWORD Errors, BytesRead;
COMSTAT ComStat;
int i;

//Check if enough bytes can be read
ClearCommError(Handle, &Errors, &ComStat);
if(ComStat.cbInQue>8)
{
//Receive
ReadFile(Handle, RxBuffer, 9, &BytesRead, NULL);

Checksum=0;
for(i=0; i<8; i++)
Checksum+=RxBuffer[i];

if(Checksum!=RxBuffer[8]) return TMCL_RESULT_CHECKSUM_ERROR;

*Address=RxBuffer[0];
*Status=RxBuffer[2];
*Value=(RxBuffer[4] << 24) | (RxBuffer[5] << 16) | (RxBuffer[6] << 8 ) | RxBuffer[7];
} else return TMCL_RESULT_NOT_READY;

return TMCL_RESULT_OK;
}


int main(int argc, char* argv[])
{
int i;
int Type, Motor, Velocity, Position;
UCHAR Address, Status; 
int	Value, Timeout;

HANDLE RS232Handle;

RS232Handle=OpenRS232("COM5", 9600);

printf("TMCL-Test\n");

do
{
printf("1 - ROR\n");
printf("2 - ROL\n");
printf("3 - MST\n");
printf("4 - MVP\n");

printf("\n99 - End\n");

scanf("%d", &i);
switch(i)
{
case 1: 
printf("Motor: ");
scanf("%d", &Motor);
printf("Velocity:");
scanf("%d", &Velocity);
SendCmd(RS232Handle, 1, TMCL_ROR, 0, Motor, Velocity);
break;

case 2: 
printf("Motor: ");
scanf("%d", &Motor);
printf("Velocity:");
scanf("%d", &Velocity);
SendCmd(RS232Handle, 1, TMCL_ROL, 0, Motor, Velocity);
break;

case 3: 
printf("Motor: ");
scanf("%d", &Motor);
SendCmd(RS232Handle, 1, TMCL_MST, 0, Motor, 0);
break;

case 4: 
printf("Motor: ");
scanf("%d", &Motor);
printf("Type (0=ABS, 1=REL, 2=COORD):");
scanf("%d", &Type);
printf("Position: ");
scanf("%d", &Position);
SendCmd(RS232Handle, 1, TMCL_MVP, Type, Motor, Position);
break;
}


if(i==1 || i==2 || i==3 || i==4)
{
Address=0;
Status=0;
Value=0;
Timeout=GetTickCount();
while(GetResult(RS232Handle, &Address, &Status, &Value)==TMCL_RESULT_NOT_READY && abs(GetTickCount()-Timeout)<1000);
printf("Result: Address=%d, Status=%d, Value=%d\n", Address, Status, Value);
}
}
while(i!=99);

CloseRS232(RS232Handle);

return 0;
}
Ich hoffe ihr versteht was ich meine :D
Danke schon einmal im voraus.

Lieben Gruß
sirop
Beiträge: 8
Registriert: 15. Oktober 2014 11:46

Re: GUI + c++ (switch case)

Beitrag von sirop »

Bei (exklusiven) switch cases denke ich eher an:
A QRadioButton is an option button that can be switched on (checked) or off (unchecked). Radio buttons typically present the user with a "one of many" choice. In a group of radio buttons, only one radio button at a time can be checked; if the user selects another button, the previously selected button is switched off.
http://qt-project.org/doc/qt-5/qradiobu ... ml#details

Oder auch an:
Suppose you have three push buttons that determine which file you will open: "Tax File", "Accounts File", or "Report File".

In order to open the correct file, you use QSignalMapper::setMapping() to map all the clicked() signals to a QSignalMapper object. Then you connect the file's QPushButton::clicked() signal to the QSignalMapper::map() slot.
http://qt-project.org/doc/qt-4.8/signal ... lots-usage
puppetClon
Beiträge: 16
Registriert: 30. Oktober 2014 18:53

Re: GUI + c++ (switch case)

Beitrag von puppetClon »

Dankeschön,

wäre ganz cool wenn du mir die benötigte Syntax mal kurz anhand einem Beispiel zeigen könntest.

Also, drück Knopf und wähle case 1 oder so.


Bin leider Qt Neuling.

Vielen Dank.
sirop
Beiträge: 8
Registriert: 15. Oktober 2014 11:46

Re: GUI + c++ (switch case)

Beitrag von sirop »

Code: Alles auswählen

signalMapper = new QSignalMapper(this);
    signalMapper->setMapping(case1Button, 1);
    signalMapper->setMapping(case2Button, 2);
    

connect(case1Button, &QPushButton::clicked,
        signalMapper, &QSignalMapper::map);
    connect(case2Button, &QPushButton::clicked,
        signalMapper, &QSignalMapper::map);

connect(signalMapper, SIGNAL(mapped(int)),
        this, SLOT(setCase(int)));
Nun muss du noch irgendwo in deiner Klassendefinition

Code: Alles auswählen

public slots:
    void setCase(int value);
unterbringen, wo du den entsprechenden case auswählst.

Ich habe mich hier bei Signal/Slot Syntax an QT 5 http://qt-project.org/doc/qt-5/signalsa ... lots-usage gehalten.
puppetClon
Beiträge: 16
Registriert: 30. Oktober 2014 18:53

Re: GUI + c++ (switch case)

Beitrag von puppetClon »

Danke für deine Hilfe....

ich gehe jetzt mal Schritt für Schritt vor und habe eine Kleinigkeit implementiert.

Habe mal grob die GUI aufgebaut. (siehe Bild)
Wenn ich nun zwischen Betrieb Automatik oder Manuell wähle, gibt er mir dies auch im Status aus.

Code: Alles auswählen

connect(ui->automatik, SIGNAL(clicked(bool)),this,SLOT(auswahl_automatik(bool)));
    connect(ui->manuell, SIGNAL(clicked(bool)),this,SLOT(auswahl_manuell(bool)));

Code: Alles auswählen

void Motorsteuerung::auswahl_automatik(bool checked)
{
    if(checked)
    ui->textBrowser->setText("Betrieb: Automatik");
    else
    ui->textBrowser->clear();
}

void Motorsteuerung::auswahl_manuell(bool checked)
{
    if(checked)
    ui->textBrowser->setText("Betrieb: Manuell");
    else
    ui->textBrowser->clear();
}

Habe ich nun auch die Möglichkeit, die Funktion so zu erweitern, das ich nur innerhalb Automatik den Startknopf betätigen kann oder muss ich dafür die Funktion ändern (da ich ja auf ein bool warte) ?


Viele Dank.
Dateianhänge
Bildschirmfoto 2014-11-03 um 19.07.57.png
Bildschirmfoto 2014-11-03 um 19.07.57.png (34.54 KiB) 29335 mal betrachtet
sirop
Beiträge: 8
Registriert: 15. Oktober 2014 11:46

Re: GUI + c++ (switch case)

Beitrag von sirop »

Zum Beispiel so:

Code: Alles auswählen

void Motorsteuerung::auswahl_automatik(bool checked)
{
    if(checked) {
     ui->textBrowser->setText("Betrieb: Automatik");
     ui->startButton->setEnabled(checked);
    }
    else
    ui->textBrowser->clear();
}

void Motorsteuerung::auswahl_manuell(bool checked)
{
    if(checked) {
      ui->textBrowser->setText("Betrieb: Manuell");
      ui->startButton->setDisabled(checked);
    }
    else
    ui->textBrowser->clear();
}
puppetClon
Beiträge: 16
Registriert: 30. Oktober 2014 18:53

Re: GUI + c++ (switch case)

Beitrag von puppetClon »

sirop hat geschrieben:Zum Beispiel so:

Code: Alles auswählen

void Motorsteuerung::auswahl_automatik(bool checked)
{
    if(checked) {
     ui->textBrowser->setText("Betrieb: Automatik");
     ui->startButton->setEnabled(checked);
    }
    else
    ui->textBrowser->clear();
}

void Motorsteuerung::auswahl_manuell(bool checked)
{
    if(checked) {
      ui->textBrowser->setText("Betrieb: Manuell");
      ui->startButton->setDisabled(checked);
    }
    else
    ui->textBrowser->clear();
}
An Button sperren habe ich echt gar nicht gedacht :D Danke.

Kann ich dem Programm sagen, dass es nach dem Compilieren automatisch eine Funktion startet, in der steht, das der Motor bereit ist, aber kein Button auswählbar ist? Sodass der User erst auf automatisch oder manuell klicken muss?



Ich weiß die Fragen sind ziemlich simpel -_-, ich danke dir das du dir die Mühe machst und mir unter die Arme greifst :)
sirop
Beiträge: 8
Registriert: 15. Oktober 2014 11:46

Re: GUI + c++ (switch case)

Beitrag von sirop »

Du kannst es mit

Code: Alles auswählen

void 	setVisible ( bool visible )
versuchen.
puppetClon
Beiträge: 16
Registriert: 30. Oktober 2014 18:53

Re: GUI + c++ (switch case)

Beitrag von puppetClon »

Und wie würde die Funktion dafür sorgen, das direkt nach Start des Programm alle Buttons ausgegraut sind?

Stehe wohl gerade auf dem Schlauch :D
sirop
Beiträge: 8
Registriert: 15. Oktober 2014 11:46

Re: GUI + c++ (switch case)

Beitrag von sirop »

puppetClon hat geschrieben:Und wie würde die Funktion dafür sorgen, das direkt nach Start des Programm alle Buttons ausgegraut sind?

Stehe wohl gerade auf dem Schlauch :D
Ausgrauen geht eher mit setDisabled(bool) angewendet auf verschiedene einzelne child widgets.
Wenn du aber setVisible benutzt, dann kannst du, wie der Name schon sagt, einzelne child widgets zunächst unsichtbar machen,
nach der Auswahl von Automatik/Nanuell dann aber wieder sichtbar.

Du hast also irgendwo:

Code: Alles auswählen

ui->setupUi(this)
so wird dein GUI "aufgesetzt".
Danach kannst Du:

Code: Alles auswählen

ui->startButton->setVisible(false);
ui->einAnderesChildWidget->setVisible(false);
umd so weiter.
puppetClon
Beiträge: 16
Registriert: 30. Oktober 2014 18:53

Re: GUI + c++ (switch case)

Beitrag von puppetClon »

Vielen Dank,

ich werde jetzt mal ein wenig probieren, wenn ich ein Frage habe, melde ich mich :)
Antworten