Datum:
Angehängte Dateien:Hi,
zurzeit beschäftige ich mit dem Programm Qt, habe gesehen das man
grafische Oberflächen damit programmieren kann. Nun habe ich einen
Tachoinstrumenten programmiert und bin wie folgt vorgegangen.
Habe mir in Gimp die Bilder eines Tachos zusammen geschnitten und mit
dem QT Designer die einzelnen png Bilder plaziert ein die Nadel jetzt
auch zum laufen gebracht. Ich habe für die Programmierung slider benutzt
mit der man durch ziehen des des Buttons der Geschwidisgkeitszeiger
bewegt wird.
Nun zu meiner Frage ich möchte gerne die Pfeiltaste auf der Tastatur
benutzen damit sich der Zeiger bewegt, habe in der bibliothek nicht
gescheites gefunden, was mich weiterbringt, vielleicht könnt ihr mir
weiterhelfen??
Hier ist der Code für die Rotaion des Zeigers:
[
Image {
id: zeiger
x: 218; y: 0
height: 215
smooth: true
source: "geschw_zeiger.png"
transform: Rotation {
id: zeigerRotation
origin.x: 5; origin.y: 215
//! [needle angle]
angle: Math.min(Math.max(-150, root.value*3.5 - 200), 150)
Behavior on angle {
SpringAnimation {
spring: 0.4
damping: .15
}
}
//! [needle angle]
}
}
]
ich danke euch schonmal im Voraus.
Gruss
Flat
Datum:
Hallo, sollte der gezeigte Code "QML" darstellen, dann würde ich die Verwendung von "QML Keys Element" (http://doc.qt.nokia.com/qml-keys.html) empfehlen.
Datum:
Hi,
Danke nochmal für deine Antwort. Nun habe ich jetzt das Problem, dass
ich nicht genau weis wie ich das eingeben soll.
Wo ich noch den Slider benutzt habe wurde der Zeiger mit einem
Eingabewert Value bewegt.
Ich will das der Value wert, wenn ich jetzt auf die Up Taste drauf
drücke, hoch zählt.
Ich hoffe ich konnte mich verständlich ausdrücken.
Hier ist ein Abschnitt vom Code:
Zeiger {
id: zeiger
x: 420
y: 80
anchors.verticalCenterOffset: 0
anchors.horizontalCenterOffset: 0
anchors.centerIn: parent
value: 20
Keys.onPressed: { if (event.key == Qt.Key_Up);
???
}
Ich bin neu in Qml, deshalb würde ich mich eure Hilfe freuen.
Ich danke schonmal im Voraus.
Datum:
Hi, habe das jetzt so gelöst indem ich den value wert mit der Up taste auf 100 rotiert lasse und mit der Down Taste auf 0. Hier ist der Code:
focus: true
Keys.onPressed: { if (event.key === Qt.Key_Up)
root.value= 100;
else if (event.key ===Qt.Key_Down)
root.value= 0
}
|
Nun möchte ich aber nur eine Taste benutzen. Sprich wenn ich auf Up drücke soll es auf den Value wert = 100 laufen und wenn ich loslasse dann soll es auf den value wert = 0 zurück rotieren. Und ich habe gleich noch eine frage, wie kann ich den Value wert anzeigen lassen, sodass man z.B nicht auf die Nadelstellung achten muss sondern den Wert direkt ablesen kann. Ich danke für eure Tipps Gruss Flat
Datum:
z.B.
// Text anzeigen Text { id: myText text: root.value font.family: "Helvetica" font.pointSize: 24 color: "red" } Keys.onPressed: { if (event.key == Qt.Key_Right) { root.value = 100; } } Keys.onReleased: { if (event.key == Qt.Key_Right) { root.value = 0; } } |
Datum:
Da die Pfeiltasten "auto repeat Keys" sind, besser so:
Keys.onPressed: {
if (event.key == Qt.Key_Up && !event.isAutoRepeat) {
root.value = 100;
}
}
Keys.onReleased: {
if (event.key == Qt.Key_Up && !event.isAutoRepeat) {
root.value = 0;
}
}
|
Datum:
Wenn das laufen nach und nach passieren soll musst du halt zusätzlich noch einen Timer zum hoch/runterzählen verwenden.
Datum:
Hi, ich bins nochmal weiß hier jemand wie ich den Timer integrieren kann, sodass ich den digitalen Wert von Tacho zählen lassen kann. Ohne Timer wird bei mir nur 100 und 0 angezeigt. Es ist vielleicht ne Triviale Frage für euch aber würde mich auf eine Hilfestellung trotzdem freuen. Gruss Flat
Datum:
Was geht denn nicht?
Datum:
Hi, du meintest ja wenn das laufen nach und nach passieren soll, muss man einen Timer integrieren, ich weiß nur nicht wie. Hast du vielleicht ein Beispiel Code, wie man das realisieren kann. Wenn die Nadel bei 200 steht soll als digitalen Wert auch 200 angezeigt werden. Kann mir hier einer helfen? Gruss Flat
Datum:
Flat schrieb: > Hi, > > du meintest ja wenn das laufen nach und nach passieren soll, muss man > einen Timer integrieren, ich weiß nur nicht wie. Hast du denn schon gefunden, wie ein Timer hier prinzipiell funktioniert? Ein Timer ist nichts anderes, als eine Möglichkeit, wie du in regelmässigen Zeitabständen Code ausführen lassen kannst. Und das kannst du jetzt mit einer zusätzlichen Variablen dazu benutzen, eine nachlaufende Variable zu erzeugen. Deine Tastendrücke setzen nicht mehr root.value auf einen bestimmten Wert, sondern eine andere Variable. Nennen wir sie mal den Sollwert. In der Timerfunktion vergleichst du bei jedem Aufruf diesen Sollwert mit root.value und wenn root.value kleiner als der Sollwert ist, dann erhöhst du es um zb. 1. Ist es größer dann verringerst du root.value um 1. Was erreichst du dadurch: der für die Funktionalität 'Zeigerrotation' zuständige Wert ändert sich in diskreten Zeiteinheiten (die durch den Timer vorgegeben sind) immer nur um 1 Einheit. Und zwar nur dann, wenn es eine Abweichung von diesem Sollwert gibt. root.value 'läuft diesem Sollwert' hinterher. Beispiel. root.Value sei 0 In deinen Tastenfunktionen setzt du den Sollwert auf 100 und die Timerfunktion wird alle 0.01 Sekunden aufgerufen Sekunden Sollwert root.value 0.00 0 0 Ausgangszustand 0.01 0 0 Jetzt drückst du die Taste und setzt den Sollwert auf 100 0.02 100 0 value ist kleiner als der Sollwert, Also wird value erhöht 0.03 100 1 0.04 100 2 0.05 100 3 ... 1.01 100 99 1.02 100 100 value und Sollwert sind gleich, also passiert nichts weiter 1.03 100 100 1.04 100 100 Du lässt die Taste los und dein Code setzt daher den Sollwert auf 0 1.05 0 100 jetzt ist value größer als Sollwert, daher wird in der Timerfunktion value um 1 verringert 1.06 0 99 1.07 0 98 ... in der Timerfunktion wird value langsam dem Sollwert nachgeführt. Ist value kleiner als der Sollwert, dann wird value um 1 erhöht. Beim nächsten Aufruf der Timerfunktion kurze Zeit später passiert ja wieder das gleiche, da wird dann value erneut erhöht, wenn es immer noch kleiner ist. Ist value größer als der Sollwert den wird value verringert. Von Ausserhalb setzt du nicht mehr den value sondern den Sollwert. Der Timermechanismus sorgt dann dafür, dass value langsam und in Schritten sich diesem Sollwert annähert. Im Endeffekt bedeutet das dann für dich: Du drückst eine Taste und der Zeiger bewegt sich in kleinen Schritten auf den zugehörigen Wert. Sind die Schritte klein genug und erfolgen sie schnell genug, dann "dreht" dein Zeiger entsprechend auf den Sollwert. Aber erst mal musst du rausfinden, wie du da einen Timer ins System kriegst, wie du ihm sagst, in welchen Zeitabständen welcher Code ausgeführt werden soll. Jetzt bist du drann die Doku zu durchforsten, wie das geht.
Datum:
Hi, sorry das ich mich so spät melde, hatte noch eine Menge zu tun. Super!!! Vielen dank nochmal für deine Antwort. Jetzt kann ich es mir wenigstens vorstellen, wie das geht. Ich mach mich die Tage dann an die Arbeit, ich schreib dann den Quellcode hier rein, wenn ich was gescheites zusammengebastelt habe :) Was ich immer Fragen wollte, also folgendes bei meinem Rechner zu Hause ruckelt der Zeiger wenn es bewegt wird. Und wenn ich beide Zeiger bewege ist es meist schlimmer. Die Zeiger bleiben stehen und es stürzt ab. Doch auf meinem Laptop funktioniert das ganze flüssig, okey es hat etwas mehr Leistung als mein Rechner und hat eine Grafikkarte. Der Rechner zu Hause, der hat nur eine OnBoard Grafikkarte, hat aber 4GB Arbeitsspeicher und ein Prozessor mit 3GHz Dual Core, es ruckelt stark. Liegt es an der Grafikkarte oder meint ihr der Prozessor ist auch schwach? Eventuell werde ich mir dann eine Grafikkkarte kaufen müssen. Ich danke schonmal für eure Antworten. Muss diese Seite echt loben, habe auch das gleiche in ein qt Forum gepostet und mir wurde nicht oder unzureichend geholfen. Ihr seid super :)
Datum:
Flat schrieb: > Der Rechner zu Hause, der hat nur eine OnBoard Grafikkarte, hat aber 4GB > Arbeitsspeicher und ein Prozessor mit 3GHz Dual Core, es ruckelt stark. Könnte eine Sache des Grafiktreibers sein. Grundsätzlich hast du mit 3Ghz eine Rechenleistung an der Hand, die für die meisten Menschen unvorstellbar hoch ist. OK, das BS frisst dir da wieder vieles weg und durch die diversen Softwareschichten wird das ganze auch nicht schneller. Aber meistens ist das eine Treibersache und ob der Treiber die vorhandene Hardware gut ausnutzt.
Datum:
Hmm an den treibern kann es nicht liegen, Ich habe die aktuellsten Treiber installiert schon vor dem aufsetzen von Windows, und das ist grad mal ein Monat her. Vielleicht liegt es ja doch an der Onboard-Grafikkarte. Ich weiß ich frag zuviel aber kam bei diesen Sache nicht weiter. Ich habe auch einiges im Internet darüber gefunden aber, hat nicht so recht funktioniert. Es geht darum, dass ich die Anwendung die ich erstellt habe an einem anderen Rechner ausführen möchte. So nun habe ich herausgefunden, dass ich das dynamisch linken muss und die dazugehörigen dlls in den Ordner mit einfügen muss, habe ich auch soweit gemacht. Wenn ich jetzt die exe Datei starte bekomme ich ein weißes Fenster. Was mache ich falsch. Habe die folgenden Dlls reingepackt: libgcc_s_dw2-1.dll mingwm10.dll QtCore4.dll QtDeclarative4.dll QtGui4.dll QtNetwork4.dll QtScript4.dll QtSql4.dll QtXmlPatterns4.dll Wenn ich diese Dlls nicht reinmache, gibt der mir ne Fehlermeldung, nachdem ich sie alle nacheinander reingemacht habe, zeigt es mir nun ein weißes Fenster an. Wisst ihr was noch fehlt?
Datum:
Starte die .exe mal über die Komandozeile (cmd.exe), dann solltest du eigentlich eine Fehlermeldung bekommen, welche dir eventuell weiterhilft.
Datum:
Angehängte Dateien:Hi, hab es jetzt hinbekommen, die zeigerstellung digital anzeigen zu lassen, dafür habe ich die Winkelstellung des Zeigers genommen. Doch jetzt habe ich das Problem das es mir den Wert in Komma anzeigt, also wie im Bild angezeigt. Wie kann ich es ohne Komma darstellen lassen?
Text {
id: myText
x: 167
y: 139
width: 107
height: 45
text: zeigerRotation.angle
font.family: "Helvetica"
font.pointSize: 24
color: "red"
}
|
@ ich danke für deine Antwort, ich bekomme leider keine Fehlermeldung, der mich weiterbringt. Es öffnet sich wieder ein weißes Fenster, doch es tut sich nichts... Weisst du vielleicht was noch fehlt oder was ich falsch mache?
Datum:
Kann mir denn hier keiner weiterhelfen? Die Antwort ist möglicherweise trivial aber ich komme nicht darauf..
Datum:
Zur Ausgabe sollte
zeigerRotation.angle.toPrecision(0) |
helfen. Ansonsten würde es helfen, wenn du das komplette Projekt hier anhängen würdest.
Datum:
Nachtrag: benutze Math.round(x) anstatt .toPrecision(x). Zum Ausführen auf einem anderen Rechner: hast du die .qml Dateien und die verwendeten Bilder auch auf den anderen Rechner kopiert?
Datum:
Angehängte Dateien:Hi, Vielen Dank für deine Antwort. Habe das jetzt das mit der digital Anzeige hinbekommen, indem ich
zeiger2Rotation.angle.toFixed() |
geschrieben habe. Kannst du vielleicht noch reinschauen, wie ich das mit dem dynamisch linken machen muss. Ich stell dir das Projekt hier zur Verfügung. Der Blinker funktioniert auch nicht so richtig, wollte es eigentlich so machen das wenn ich auf Links drücke auf der Tastatur das es Links blinkt, wenn ich nochmal Links drücke soll das blinken aufhören. mit Rechts das gleiche. Für Anregungen, Ratschläge und Tipps wäre ich euch sehr dankbar :) Gruss Flat
Datum:
Okey das mit dem Blinker habe ich jetzt hinbekommen es geht. hier der code :
onArrowChangedChanged:{
// console.log("in arrow change");
blinkerTimer1.stop();
blinkerTimer2.stop();
blinkerTimer3.stop();
if (arrowChanged == 3){
leftArrowOn = true;
rightArrowOn = false;
blinkerTimer3.start();
return;
}else if (arrowChanged == 2){
leftArrowOn = false;
rightArrowOn = true;
blinkerTimer2.start();
return;
}else if (arrowChanged == 1){
leftArrowOn = true;
rightArrowOn = true;
blinkerTimer1.start();
return;
}else if (arrowChanged == 0){
leftArrowOn = false;
rightArrowOn = false;
return;
}
}
Timer {
id:blinkerTimer1
interval: 500;
repeat: true
onTriggered: {
if (leftArrowOn == false || rightArrowOn == false ){
leftArrowOn = true;
rightArrowOn = true;
}
else {
leftArrowOn = false;
rightArrowOn = false;
}
}
}
Timer {
id:blinkerTimer2
interval: 500;
repeat: true
onTriggered: {
if (rightArrowOn == false ||
rightArrowOn == false && leftArrowOn == true){
leftArrowOn = false;
rightArrowOn = true;
}
else{
leftArrowOn = false;
rightArrowOn = false;
}
}
}
Timer {
id:blinkerTimer3
interval: 500;
repeat: true
onTriggered:{
if (leftArrowOn == false ||
rightArrowOn == true && leftArrowOn == false){
leftArrowOn = true;
rightArrowOn = false;
}
else{
leftArrowOn = false;
rightArrowOn = false;
}
}
}
|
Einfach in die Blinker.qml Datei rein kopieren In die Main.qml kommt das rein. Dann muss es funktionieren.
Blinker {
id: blinker1
x: 0
y: 4
anchors.verticalCenterOffset: 4
anchors.horizontalCenterOffset: 0
anchors.centerIn: parent
focus: true
Keys.onRightPressed:{
blinker1.arrowChanged = 2;
}
Keys.onLeftPressed: {
blinker1.arrowChanged = 3;
}
Keys.onDownPressed: {
blinker1.arrowChanged = 0;
}
Keys.onSpacePressed:{
blinker1.arrowChanged = 1;
}
}
|
Vielleicht habe ich es etwas umständlich gemacht aber hauptsache es funktioniert erst einmal :) Könnt ihr mir vielleicht noch helfen, wie ich das mit dem dynamisch linken machen muss. Das Projekt steht zur Verfügung. Ich wäre euch sehr dankbar dafür. Gruss Flat
Datum:
Dein Problem ist nicht das dynamische linken, sondern vermutlich die Tatsache das QML eine Interpretersprache ist. Was heißt, dass deine QML Dateien erst zur Programmlaufzeit interpretiert werden. Wenn du die kompilierte Programmdatei (*.exe) an einem anderen Ort ausführen möchtest, hast du nun zwei Möglichkeiten. Zum einen kannst du deinen QML/ Ordner (*) zusammen mit den DLL Dateien, in den selben Ordner wie deine Programmdatei kopieren. Falls du lieber alles in einer Datei hast, kannst du stattdessen auch das Qt Ressourcen System nutzen, um deinen QML/ Ordner als Binärdaten mit in deine Programmdatei zu packen (linken). Eine Anleitung dazu findest du unter: http://doc.qt.nokia.com/4.7-snapshot/qtbinding.htm... * Der Ordner welcher die gesamten .qml Dateien sowie die verwendeten Bilder enthält.
Datum:
Angehängte Dateien:@ ich Vielen dank für deine ausführliche Antwort. Ich habe noch ein anderes Problem, was ich nicht gebacken bekomme. Und zwar möchte ich die Tacho nadel mit einem Mikrocontroller ansprechen, sprich wenn ich auf ein Taste vom Mikrocontroller drücke soll die Nadel rotieren, habe bis jetzt immer die Tastatur benutzt. Über die serielle Schnittstelle RS-232 soll der Mikrocontroller angesprochen werden. Die Kommunikation über die Mikrocontroller seite habe ich soweit, Nun möchte ich die Daten, die vom Mikrocontroller geschickt werden über den ComPort mit QT lesen. Ich habe einige Programme gefunden, doch ich bekomme bei jedem Programm, die ich kompiliere eine Fehlermedlung, dass die include Dateien nicht gefunden werden können, obwohl sie in dem richtigen Ordner vorhanden sind. Ich lade euch mal das Programm hier hoch. Ich bin genau den schritten gefolgt wie im Link. Ich verstehe irgendwie nicht wie ich das mit dem Build Ordner und qmake und make ausführen soll. Nachdem ausführen kommt die Fehlermedlung Warnung:Unable to find file for inclusion \src\qt4support\serialport.prf [[http://qt-project.org/wiki/QtSerialPort#b55bbb687c...]] Vielleicht habt ihr auch andere funktionierende Programme. Ich hoffe ihr könnt mir weiterhelfen, bin hier am verzweifeln... Gruss Flat
Datum:
Hallo Flat, bei QT Fragen ist das qtforum.de besser geeignet. Zur Kommunikation eignet sich anscheinend qextserialport am besten. Suche mal danach. In der qextserialport sollte es sogar über Signale und Slots funktionieren. Ich bin auch gerade dabei diese zu testen.Ich habe erstmal die Version 1.2 für QT4 benutzt. Oder: Irgendwo im Netz gibt es eine Qarduino 2.zip Datei. Dort ist auch eine Kommunikation mit rs232 eingebaut. Allerdings wie ich gesehen habe nicht mit Signale und Slots. Links: http://docs.qextserialport.googlecode.com/git/1.2/... http://docs.qextserialport.googlecode.com/git/1.2/index.html Allerdings mußte ich auch in den .h Dateien etwas herausnehmen,da ich unter Linux entwickle. Jogibär
Datum:
Die Anleitung auf die Du verlinkt hast ist wohl etwas älter und stimmt nicht mehr ganz. Erstelle im Ordner mit der serialport.pro einen neuen Ordner mit z.B. dem Namen build. Wechsle in den eben erstellten Ordner:
cd build |
Führe qmake aus:
qmake ../serialport.pro |
Führe make aus:
make make install |
unter Windows musst du das ganze eventuell dann nochmal mit Config= release ausführen. (Den Inhalt des Ordners build vorher löschen.) Also:
qmake ../serialport.pro CONFIG+=release |
und nochmal make wie gehabt:
make make install |
Dann sollte es eigentlich funktionieren.
Datum:
Hi Jogibär, danke für deine Antwort. Ich kenne die Seite qtforum.de auch, habe da auch mal da Fragen reingestellt aber mir wurde nicht bzw. unzureichend geholfen. Hier wurde mir immer geholfen, auch wenn es keine explizite Seite für QT ist. Wir sollten vielleicht die Seite umbenennen, mikrocontroller_QT.net oder so :) Spass bei Seite kannst du mir vielleicht dein Programm zukommen lassen, wenn du es zum laufen bekommen hast. Werde die Sachen mir mal genau anschauen und hier rein posten wenn es funktioniert. Gruss Flat
Datum:
Flat schrieb: > Hi Jogibär, > > danke für deine Antwort. > Ich kenne die Seite qtforum.de auch, habe da auch mal da Fragen > reingestellt aber mir wurde nicht bzw. unzureichend geholfen. Ja,das kann ich leider auch bestätigen. Die sind dort etwas elitär. Aber ab es gibt auch Personen, die ausgezeichnet antworten. > Hier wurde mir immer geholfen, auch wenn es keine explizite Seite für QT > ist. > Wir sollten vielleicht die Seite umbenennen, mikrocontroller_QT.net oder > so :) > Spass bei Seite kannst du mir vielleicht dein Programm zukommen lassen, > wenn du es zum laufen bekommen hast. Das Projekt ist etwas größeres. Frag in ein paar Jahren noch mal nach ;-). > Werde die Sachen mir mal genau anschauen und hier rein posten wenn es > funktioniert. > > Gruss > > Flat Jogibär
Datum:
Angehängte Dateien:Hi, ich habe endlich ein funktionierendes Programm gefunden, dass auf die serielle Schnittstelle zugreifen kann. Habe auch schon mit einem Mikrocontroller Daten gesendet und mit dem Beispielprogramm die Daten empfangen. Nun zu meiner Frage, da ich mich nicht sonderlich mit C++ auskennen und mich dafür in QML eingearbeitet habe, möchte ich wissen, ob ich nun was ich in QML erzeugt habe in die c++ datei integrieren kann. Sprich mit Signals und Slots Ich möchte wenn ich jetzt vom Mikrocontroller auf die Taste draufdrücke eine byte verschicken sagen wir mal (1111 1111), der Zeiger soll jetzt bei diesem code anfangen zu laufen und wenn ich wieder loslasse soll es wieder runterlaufen (0000 0000). Ich habe im Programm das Beeispiel mit dem PortListener herausgeschrieben. Jetzt möchte ich wenn ich ein Signal von 1111 1111 bekomme den Zeiger, was ich qml geschrieben habe per Signal und Slot bewegen. Es hört sich vielleicht trivial an aber für mich der nicht so gute Kenntnisse in c++ Programmieren hat ist es schon etwas aufwändiger, daher würde ich mich für eure Tipps und Lösungsvorschläge freuen. Ich habe das BeispielProgramm mit der Serielle Schnittstelle angehängt. Das andere Programm womit die Zeiger bewegt werden können sind auch weiter oben im Thread enthalten.
#include "PortListener.h" #include <QtDebug> PortListener::PortListener(const QString & portName) { qDebug() << "hi there"; this->port = new QextSerialPort(portName, QextSerialPort::EventDriven); port->setBaudRate(BAUD9600); port->setFlowControl(FLOW_OFF); port->setParity(PAR_NONE); port->setDataBits(DATA_8); port->setStopBits(STOP_2); if (port->open(QIODevice::ReadWrite) == true) { connect(port, SIGNAL(readyRead()), this, SLOT(onReadyRead())); connect(port, SIGNAL(dsrChanged(bool)), this, SLOT(onDsrChanged(bool))); if (!(port->lineStatus() & LS_DSR)) qDebug() << "warning: device is not turned on"; qDebug() << "listening for data on" << port->portName(); } else { qDebug() << "device failed to open:" << port->errorString(); } } void PortListener::onReadyRead() { QByteArray bytes; int a = port->bytesAvailable(); bytes.resize(a); port->read(bytes.data(), bytes.size()); qDebug() << "bytes read:" << bytes.size(); qDebug() << "bytes:" << bytes; } void PortListener::onDsrChanged(bool status) { if (status) qDebug() << "device was turned on"; else qDebug() << "device was turned off"; } |
Ich danke euch schonmal im Voraus Freundliche Grüsse Flat
Datum:
Hab nun das Problem, dass ich nicht weiß wie ich die Zeiger zum laufen bringe, da ich alles in qml geschrieben habe und der Serial Port in c++ geschrieben ist. Könnt ihr mir vielleicht sagen wie ich das mit einander verknüpfen kann. Habe auch schon danach gegoogelt aber wurde nicht so richtig fündig bzw. der Lösungsansatz ist mir nicht so richtig klar. Habe das hier gefunden : http://doc.qt.nokia.com/4.7-snapshot/qtbinding.html Das was ich haben möchte ist den root.value Wert in c++ ändern wenn ein Signal von der Seriellen Schnittstelle kommt. Hier ist der Qml Code vom Zeiger:
Image {
id: zeiger
x: 235; y: 12
width: 11
height: 228
smooth: true
source: "GeschwZeiger.png"
transform: Rotation {
id: zeigerRotation
origin.x: 5; origin.y: 225
//! [needle angle]
angle: Math.min(Math.max( root.value * 3 -150 ), root.value +50)
//Math.min(Math.max(-150, root.value*3.5 - 200), 150)
Behavior on angle {
SpringAnimation {
spring: 0.08
damping: .25
}
}
//! [needle angle]
}
}
|
Datum:
Kann mir denn hier keiner weiterhelfen? Die Antwort ist möglicherweise trivial aber ich komme nicht darauf..
Datum:
@ ich du konntest mir bis jetzt immer bei meinen Fragestellungen helfen. hast du vielleicht ein Tipp wie man das Problem lösen kann. Wäre dir sehr dankbar. Freundliche Grüße Flat
Datum:
Hallo, auf QML Properties kannst du z.B. mit QDeclarativeProperty zugreifen. Beispiel: Du erstellst in deinem QML root Objekt eine Property und weist diese dann z.B. deinem Zeiger zu. z.B. main.qml
import QtQuick 1.0
//! [imports]
//! [0]
Rectangle {
color: "#545454"
width: 1280
height: 600
focus: true
property int zeigerVal
// Dial with a slider to adjust it
Zeiger {
id: zeiger
anchors.centerIn: parent
value: zeigerVal
}
|
Im C++ Code kannst du nun mit QDeclarativeProperty diesen Wert verändern: #z.B. main.cpp
#include <QtGui/QApplication> #include <QtDeclarative> #include "qmlapplicationviewer.h" Q_DECL_EXPORT int main(int argc, char *argv[]) { QApplication app(argc, argv); QDeclarativeView view; view.setSource(QUrl("qml/tacho/main.qml")); view.show(); QDeclarativeProperty property(view.rootObject(), QString("zeigerVal")); property.write(50); return app.exec(); } |
Datum:
@ ich Du bist mein Held. Es funktioniert :) Danke Vielmals. Nun habe ich das Problem mit dem Byte senden, da ich später die Blinker und die Zeiger einzeln ansteuern möchte, brauche ich einen kleinen Quellcode mit dem ich dies Realisieren kann. Wie kann ich die Propertys nun ändern wenn ich sagen wir mal ein byte von 0x01 sende? Ich hoffe ich habe mich verstandlich ausgedrückt. Hoffe du kannst mir hierbei auch helfen. Gruss Flat
Datum:
Wenn ich dich jetzt richtig verstanden habe und abhängig davon wie dein C++ Programm aufgebaut ist, könnte die Datenübergabe in etwa so aussehen:
//main int main(int argc, char *argv[]) { QApplication app(argc, argv); QDeclarativeView view; view.setSource(QUrl("qml/tacho/main.qml")); view.show(); MyQmlInterface interface(view); return app.exec(); } //MyQmlInterface class MyQmlInterface : public QObject { Q_OBJECT public: MyQmlInterface(const QDeclarativeView &view, QObject *parent = 0) //Verbindungen zu den Propertys initialisieren : myProp1(view.rootObject(), "zeigerVal"), myProp2(view.rootObject(), "..."), ... { ... } public slots: void newData(int type, int val) { //abhängig von type, den Wert val in die gewünschten Property schreiben switch (type) { case 1: myProp1.write(val); break; case 2: myProp2.write(val); break; ... } } private: QDeclarativeProperty myProp1; QDeclarativeProperty myProp2; ... } //in der Klasse, welche die Dtaen vom uC empfängt, erstellst ein entsprechendes Signal // z.B. Signal: void sendNewData(int type, int val); //Dann verbindest du das Signal und den Slot, an entsprechender Stelle und dann kannst //du in deiner Empfangsroutine, nachdem du die empfangenen Daten dekodiert hast, das Signal versenden: emit sendNewData(typeFromUc, valFromUc); |
Datum:
Angehängte Dateien:@ ich danke für deine ausführliche Antwort. Da ich nicht mich nicht so gut auf C++ basis auskenne, würde es mir sehr helfen, wenn du mal in mein Programm reinschauen könntest. Habe es mir ehrlich gesagt etwas einfacher vorgestellt oder ich sehe die sache zu kompliziert. Ich habe ein Klasse erstellt, die du vorgeschalgen hast, doch nun weiss ich nicht genau, wie ich das mit dem Signals and slots verbinden soll und dann noch die Empfangsroutine anpassen soll. Für Tipps würde ich mich sehr freuen. Als Anlage habe ich das gesamte Projekt angehangen, was ich bis jetzt gemacht habe, lass dich nicht von den vielen qml Dateien irritieren, habe sie nicht alle benutzt. Die Haupt Qml Datei ist die main.qml Gruss Flat
Datum:
Guten Morgen, kann mir hier jemand behiflich sein. Habe das Projekt angehangen. Der Mikrocontroller schickt hier 0x10 für den Zeiger und 0x20 für den Warnblink.
int main(void) { //##### INIT ######## uint8_t state = 0; UART_Init(); sei(); //Global interrupt ein // EMD("\nInitialisiert\n"); //##### ENDE INIT ######## DDRD=0; //Tasten-PORT auf Eingang PORTD=255; //pullup DDRB=255; //LED-PORT auf Ausgang PORTB=255; //LED aus // Initialisierung wie oben while(1) { if ((PIND & (1<<4)) == 0) { // Schalter gedrückt // state = (state + 1) % 2; // Zustand ändern // PORTB = state?255:0; // und ausgeben (alle Pins) // _delay_ms(1000); // 1 s warten UART_sendByte(0x10); // Geschwindigkeitszeiger } if ((PIND & (1<<7)) == 0) { UART_sendByte(0x20); //Warnblink } } } |
Nun möchte ich in der Empfangsroutine die den Code anpassen und die Signals und Slots einfügen. Kann mir einer dabei behilflich sein. Das gesamte Projekt habe ich angehangen. Gruss Flat
Datum:
ich habe den zeiger nun versucht mit dem folgenden Code zu bewegen, hat
leider nicht funktioniert :(
Ich kann den string auslesen mit dem Portlistener, doch der Zeiger
bewegt sich nicht
Mikrocontroller Seite:
while(1) {
if ((PIND & (1<<4)) == 0) { // Schalter gedrückt
UART_sendString("Zeiger");
}
if ((PIND & (1<<7)) == 0) {
UART_sendString("Warnblink");
}
}
Empfang des der main.cpp
QDeclarativeProperty property(view.rootObject(), QString("zeigerVal"));
QByteArray bytes;
if(bytes == "Zeiger" ){
property.write(100);
}
if (bytes == "" ) {
property.write(0);
};
Das Problem liegt wahrscheinlich das ich einen String wert schicke und
QByteArray char Werte weiterverarbeitet.
Wie kann ich jetzt die String Werte in char umwandeln oder char werte in
String.
Lieg ich mit meiner Vermutung richtig oder bin ich auf dem ganz flaschen
Weg??
Datum:
Flat schrieb: > Empfang des der main.cpp > > QDeclarativeProperty property(view.rootObject(), QString("zeigerVal")); > > > QByteArray bytes; > if(bytes == "Zeiger" ){ > mir erschliesst sich nicht, wie da jetzt der Zusammenhang ist, dass in 'bytes' irgendwie magisch die Werte von der UART auftauchen. Warum sollen die das tun? Generell: verzichte darauf, ganze Wörter zu verschicken. Du hast keine Garantie, dass von einem Leseversuch auf dem PC zum nächsten auch tatsächlich das ganze Wort schon übertragen wurde. D.h. das ist zusätzlicher Aufwand sicherzustellen, dass der Empfänger auch weiß, wann eine Übertragung zu Ende ist und nichts mehr kommt. Der Sender hätte ja auch "Zeigerlager" schicken können. Am einfachsten ist es immer noch, wenn du dich auf 1-buchstabige Kommandos beschränkst. Dann fällt dieses 'Problem' erst mal flach, denn 1 Buchstabe wird immer komplett übertragen, ehe ihn der Empfänger zu Gesicht bekommt. PS: Hast du eigentlich schon getestet, ob deine UART Übertragung grundsätzlich funktioniert? Sprich: In einem Terminal-Progamm nachgesehen, ob da auch wirklich das ankommt, was ankommen sollte? Das ist nämlich keineswegs selbstverständlich und wenn die Kommunikation grundsätzlich nicht funktioniert, dann brauchst du auf höheren Ebenen erst mal nicht weiter machen, solange dieses Problem nicht gefixt ist. Auch solltest du schrittweise vorgehen. Nicht gleich die komplette Kette vom µC zum Zeigerinstrument in Betrieb nehmen und hoffen, das da alles funktioniert. Und hinterher großes Kopfkratzen, warum nichts funktioniert. Erst mal mit einem Terminalprogramm nachsehen, ob die Kommunikationsebene funktioniert. Dann mit einem Programm sich an diese Kommunikation binden und empfangene Zeichen einfach so wie sie empfangen wurden ausgeben. Und erst dann mit einem Programm die Werte (sofern die vorhergehenden Tests erfolgreich waren) an das Zeigerinstrument weitergeben. Auf die Art baut jede Erweiterung immer auf bereits getesteten Komponenten auf von denen man weiß, dass sie funktionieren. Gehts trotzdem nicht, dann muss das Problem irgendwo in dem Teil sein, der gerade neu dazu gekommen ist. Und je weniger neu dazu kommt, desto weniger Möglichkeiten für Probleme und Fehler gibt es.
Datum:
Karl Heinz Buchegger schrieb: > Flat schrieb: > >> Empfang des der main.cpp >> >> QDeclarativeProperty property(view.rootObject(), QString("zeigerVal")); >> >> >> QByteArray bytes; >> if(bytes == "Zeiger" ){ >> > > mir erschliesst sich nicht, wie da jetzt der Zusammenhang ist, dass in > 'bytes' irgendwie magisch die Werte von der UART auftauchen. Warum > sollen die das tun? > > ... Ergänzung: Du hast in deiner Empfangsroutine ja bereits den passenden Emfangsslot mit entsprechender Ausgabe.
//PortListener.cpp void PortListener::onReadyRead() { QByteArray bytes; int a = port->bytesAvailable(); bytes.resize(a); port->read(bytes.data(), bytes.size()); qDebug() << "bytes read:" << bytes.size(); qDebug() << "bytes:" << bytes; } // Wenn du alle vorhandenen Bytes lesen möchtest, ist es allerdings sinnvoller es so zu schreiben: void PortListener::onReadyRead() { QByteArray bytes = port->readAll(); qDebug() << "bytes read:" << bytes.size(); qDebug() << "bytes:" << bytes; } |
Nachdem du also festgestellt hast, dass die Kommunikation mit einem Terminalprogramm funktioniert, kannst du damit feststellen, ob dein Programm die korrekten Daten empfängt. Wenn das dann funktioniert, kannst du die weiter oben beschriebene Klasse MyQmlInterface auch einfach weglassen und "view" direkt an PortListener durchreichen. Die Implementierung erfolgt dann entsprechend wie in MyQmlInterface dargestellt, nur das du die Signal-Slot Verbindung nicht benötigst. Allgemein:
//Wenn du Objekte mit new erzeugst, PortListener::PortListener(const QString & portName) { ... this->port = new QextSerialPort(portName, QextSerialPort::EventDriven); ... } //dann solltest du den Speicher auch irgendwann wieder freigeben. // Also z.B. einen Destruktor implementieren. PortListener::PortListener(const QString & portName) { delete port; } |
Datum:
PortListener::~PortListener(const QString & portName) |
So klappt es besser mit dem Destruieren :)
Datum:
Wenn du jetzt auch noch das Argument zum DTor wegnimmst, dann passts.
Datum:
Ach ja! 's ist bald Feierabend.
Datum:
Mark Brandis schrieb: > PortListener::~PortListener(const QString & portName) > So klappt es besser mit dem Destruieren :) Zumindest fast :)
PortListener::~PortListener() |
Datum:
zu spät ...
Datum:
Hi, danke für die Antworten habe das mit den Terminal Programm getestet und es funktioniert alles einwandfrei. Ich habe jetzt beim senden eine 500ms delay eingesetzt, da das Programm sonst mehrere Bytes empfangen hat statt nur "Z" . hier ist das Beispiel
while(1) { if ((PIND & (1<<4)) == 0) { // Schalter gedrückt UART_sendString("Z"); _delay_ms(500); } if ((PIND & (1<<7)) == 0) { UART_sendString("W"); _delay_ms(500); } } |
Im Programm funktioniert die Übertragung auch
also es zeigt mit in bytes read: 1
und bytes: Z an.
Doch ich weiss nicht wie ich die "view" an die den Portlistener
durchreichen soll. Also in main.cpp habe ich das reingeschrieben, doch
die bytes werden dann nicht zur Laufzeit aktualisiert. Ich möchte die
Property in Portlistener verändern können. Ich habe es bis jetzt nicht
hinbekommen.
QByteArray bytes;
if(bytes == "Zeiger" ){
property.write(100);
}
if (bytes == "" ) {
property.write(0);
};
|
Würde mich freuen, wenn du mir hierbei auch helfen könntest. Gruss Flat
Datum:
Habe es oben falsch geschrieben meinte natürlich nur "Z" So ist es richtig.
QByteArray bytes;
if(bytes == "Z" ){
property.write(100);
}
if (bytes == "" ) {
property.write(0);
};
|
Datum:
Du kannst es im Prinzip so machen, wie ich es in Beitrag "Re: Tachoanzeige in Qt programmieren" für MyQmlInterface beschrieben habe. Also: - Du erstellst dir in PortListener entsprechende Membervariablen für deine QML Properties. - Du erweiterst den PortListener Konstruktor entsprechend, um dein QML View zu übergeben. - Du initialisierst im PortListener Konstruktor deine Property Variablen entsprechend mit der übergebenen View. - Nun kannst du in PortListener::onReadyRead, deine Propertys schreiben und lesen.
Datum:
Ich habe das bis jetzt so gemacht, hier der Quellcode Portlistener.h
#ifndef PORTLISTENER_H_ #define PORTLISTENER_H_ #include <QObject> #include "qextserialport.h" #include "QDeclarativeView" class PortListener : public QObject { Q_OBJECT public: PortListener(const QString & portName); PortListener(const QDeclarativeView &view, QObject *parent = 0); private: QextSerialPort *port; QDeclarativeProperty myProp1; private slots: void onReadyRead(); void onDsrChanged(bool status); }; #endif /*PORTLISTENER_H_*/ |
hier ist der quellcode für den Portlistener.cpp
#include "PortListener.h" #include <QtDebug> #include "QDeclarativeProperty" #include "QDeclarativeView" #include <QByteArray> #include <QObject> #include <QGraphicsObject> PortListener::PortListener(const QString & portName) { qDebug() << "hi there"; this->port = new QextSerialPort(portName, QextSerialPort::EventDriven); port->setBaudRate(BAUD115200); port->setFlowControl(FLOW_OFF); port->setParity(PAR_NONE); port->setDataBits(DATA_8); port->setStopBits(STOP_1); if (port->open(QIODevice::ReadWrite) == true) { connect(port, SIGNAL(readyRead()), this, SLOT(onReadyRead())); connect(port, SIGNAL(dsrChanged(bool)), this, SLOT(onDsrChanged(bool))); if (!(port->lineStatus() & LS_DSR)) qDebug() << "warning: device is not turned on"; qDebug() << "listening for data on" << port->portName(); } else { qDebug() << "device failed to open:" << port->errorString(); } } PortListener::PortListener(const QDeclarativeView, QObject *parent) { QDeclarativeView view; view.setSource(QUrl::fromLocalFile("qml/TachoNEU/main.qml")); view.show(); QDeclarativeProperty myProp1(view.rootObject(), QString("zeigerVal")); } void PortListener::onReadyRead() { QByteArray bytes = port->readAll(); //int a = port->bytesAvailable(); //bytes.resize(a); //port->read(bytes.data(), bytes.size()); qDebug() << "bytes read:" << bytes.size(); qDebug() << "bytes:" << bytes; if(bytes == "Z" ){ myProp1.write(100); } else if (bytes == "" ) { myProp1.write(0); }; } void PortListener::onDsrChanged(bool status) { if (status) qDebug() << "device was turned on"; else qDebug() << "device was turned off"; } |
Der Quellcode für dei main.cpp
#include <QtGui/QApplication> #include "qmlapplicationviewer.h" #include "PortListener.h" #include <QDeclarativeProperty> #include <QByteArray> #include <QObject> #include <QGraphicsObject> Q_DECL_EXPORT int main(int argc, char *argv[]) { QScopedPointer<QApplication> app(createApplication(argc, argv)); /* QmlApplicationViewer viewer; viewer.setOrientation(QmlApplicationViewer::ScreenOrientationAuto); viewer.setMainQmlFile(QLatin1String("qml/TachoNEU/main.qml")); viewer.showExpanded(); */ QString portName = QLatin1String("COM1"); // update this to use your port of choice PortListener listener(portName); // signals get hooked up internally //QDeclarativeView view; // view.setSource(QUrl::fromLocalFile("qml/TachoNEU/main.qml")); // view.show(); // QDeclarativeProperty myProp1(view.rootObject(),QString("zeigerVal")); return app->exec(); } |
Ich habe das "view" in Portlistener eingesetzt , doch ich bekomme keine Fenster wenn ich in der main.cpp das "view" auskommentiere. Und wenn ich die view in main einsetze dann klappt es nicht die myProp1 Werte in Portlistener zu ändern. Ich habe dein Lösungsansatz glaub ich nicht richtig verstanden. Sorry nochmal wenn ich viele doffe Fragen stelle...
//QDeclarativeView view; // view.setSource(QUrl::fromLocalFile("qml/TachoNEU/main.qml")); // view.show(); // QDeclarativeProperty myProp1(view.rootObject(),QString("zeigerVal")); |
Irgendwas habe ich falsch gemacht, könntest kurz reinschauen was ich falsch gemacht habe. Danke nochmal für deine hilfe.
Datum:
Du kannst für eine Klasse zwar mehrere Konstruktoren definieren, beim Erstellen des Objekts, wird aber immer nur einer dieser Konstruktoren ausgeführt. Da du beim Erzeugen eines PortListener Objekts allerdings sowohl die serielle Schnittstelle, als auch deine QML Properties initialisieren möchtest, benötigst du einen Konstruktor, welcher sowohl die serielle Schnittstelle, als auch deine QML Properties initialisiert. Das Erzeugen und Anzeigen deiner QML view erfolgt also weiterhin in main und PortListener wird mit dessen Konstruktor nur eine Referenz auf das view Objekt übergeben, mit welcher er seine QDeclarativeProperty Member initialisiert. Alternativ kannst du in PortListener auch eine Initialisierungsmethode für deine QDeclarativePropertys erstellen, welche genauso als Parameter eine Referenz auf dein QML view erhält. Allerdings musst du dann sicherstellen, dass die QDeclarativePropertys in PortListener erst verwendet werden, nachdem Sie auch initialisiert wurden.
Datum:
Ja ich hab verstanden das im main.cpp das Object nur von der Qml initalisiert wurde. Die Frage ist jetzt, wie ich die Serielle schnittstelle auch in main initialisiere sodass die Werte verändert werden. Ich komme nicht mehr weiter. Kannst du eventuel einen kurzen quellcode schreiben, wäre dir sehr dankbar.
Datum:
Main bleibt im Grunde so wie gehabt. Du musst nur dem Konstruktor von PortListener zusätzlich noch view übergeben und die PortListener Klasse natürlich noch entsprechend anpassen. main() sieht dann in etwa so aus:
QDeclarativeView view;
view.setSource(QUrl::fromLocalFile("qml/TachoNEU/main.qml"));
view.show();
QString portName = QLatin1String("COM1"); // update this to use your port of choice
PortListener listener(portName, view); // signals get hooked up internally
|
Datum:
Ich habe jetzt die main.cpp wie du beschrieben hast erstellt. Die Portlistener.h habe ich so wie du es beschrieben hast erstellt Beitrag "Re: Tachoanzeige in Qt programmieren" Doch die myProp1 kann ich in public nicht so schreiben, wie du es definiert hast.
: myProp1(view.rootObject(), "zeigerVal"), |
hier der Quellcode:
#include <QObject> #include "qextserialport.h" #include "QDeclarativeView" #include "QDeclarativeProperty" class PortListener : public QObject { Q_OBJECT public: PortListener (const QDeclarativeView & view , QObject *parent = 0); PortListener(const QString & portName); private: QDeclarativeProperty myProp1; QextSerialPort *port; private slots: void onReadyRead(); void onDsrChanged(bool status); }; |
die Portlistener.cpp sieht so aus Ich weiss nicht ob ich es so richtig geschrieben habe. Kannst du bitte in den Code reinschauen und mich eventuel verbessern. Ich danke dir schonmal im voraus.
void PortListener::onReadyRead() { QDeclarativeView view; QDeclarativeProperty myProp1(view.rootObject(), QString("zeigerVal")); bytes = port->readAll(); qDebug() << "bytes read:" << bytes.size(); qDebug() << "bytes:" << bytes; if(bytes == "Z" ){ myProp1.write(100); } else if (bytes == "W" ) { myProp1.write(0); } } PortListener::PortListener(const QDeclarativeView & view , QObject *parent) { QDeclarativeProperty myProp1(view.rootObject(), "zeigerVal"); } |
Datum:
Hallo, Du meintest das nur ein Konstruktor ausgeführt wird. Wie kann ich also die view in dem Konstruktor Portname ausführen? Also wie initaliere ich die Propertys in Portname? So wie ich es geschrieben habe funktioniert es nicht Ich komme ehrlich gesagt nicht weiter:( Kannst du mir bitte helfen ?
Datum:
Ich habe es jetzt doch hinbekommen. Danke nochmal vielmals für deine Hilfestellung :) Ich habe den Zeiger jetzt auf zwei Tasten zugewiesen. Ich möchte gerne wenn ich auf eine Taste drücke das der Zeiger hoch geht und wenn ich loslasse, dass es wieder runterläuft. Hat einer ne Idee wie man es machen könnte?
Datum:
Es funktioniert jetzt alles, -----*Freu mich :) *---- Danke an alle die mir geholfen haben und einen besonderen dank an Ich.
Datum:
Angehängte Dateien:Hallo, ich habe noch ne Frage. Es geht darum das ich die Anwendung jetzt auf meinem Display anzeigen möchte. Das Display ist ein Chinch display wobei ich die Auflösung anpassen muss, damit das Rundtacho auch Kreisförmig angezeigt wird. Ich habe nun das Bild so weit gedämpft das das Rundtacho jetzt auf dem Display Kreisrund dargstellt wird, doch jetzt habe ich Probleme mit dem Zeiger, da der Tacho in wirklichkeit Eiförmig ist, laufen die Zeiger aus dem Tacho raus. Gibt es ne routine, wo ich den Zeiger entsprechend dem Tacho rotieren lassen kann. Ich hoffe ihr habt mich richtig verstanden. Ich wäre sehr dankbar, wenn ihr mir auch hierbei helfen könntet. Der Code für die Zeiger rotation bei einem Kreisrundem Tacho. Ich brauch einen Code für für das entsprechende TAcho das eingefügt worden ist.
Item {
id: root
property int value : 0
property int angle : 0
width: 338
height: 518
Image {
id: zeiger
x: 167; y: 114
width: 11
height: 190
smooth: true
source: "GeschwZeiger.png"
transform: Rotation {
id: zeigerRotation
origin.x: 0; origin.y: 150
//! [needle angle]
angle: Math.min(Math.max(root.value * 3.5 -160 ), root.value +50)
Behavior on angle {
SpringAnimation {
spring: 0.1
damping: .25
}
}
//! [needle angle]
}
}
}
|
Datum:
Hi, habe hier in youtube sowas ähnliches Youtube-Video "Guage Created In QT" Die Nadel läuft nicht über das Rundinstrument. Es passt sich an die Struktur des Rundinstrumentes an. Weiss vielleicht einer wie man so etwas realisiert ? Ich suche schon so lange danach, habe leider nichts gefunden Gruss Flat
Datum:
Weiss den keiner wie das funktioniert ?
Datum:
Hallo, Habe mein Problem jetzt so gelöst indem ich mein Rundtacho als Ellipse genommen habe, sodass das es auf dem Display, was ich habe als Kreis angezeigt wird. Damit der Zeiger nicht über die Ellipse läuft, habe ich über die Ellipsengleichung die Zeigerlänge berechnet und es passt sich an das Rundtacho an. Ellipsengleichung: (x²/a²) + (y²/b²) = 1 a und b sind die Durchmesser des Rundinstruments, wo der Zeiger entlang laufen soll. x = a* cos (Winkel) y = b* sin (Winkel) Nun habe ich die Zeigerhöhe ausgerechnet indem ich die Formel auf y umgestellt habe und durch den Satz des Pythagoras habe ich die Zeigerhöhe herausgefunden. z = Wurzel(b² + cos(Winkel)² (a²-b²)) z:Zeigerhöhe
Item {
id: root
property int value : 0
property int angle : 0
property in a: 550
property in b: 366
width: 338
height: 518
Image {
id: zeiger
x: 167; y: 114
width: 366
height: Math.sqrt((root.b*root.b) + (Math.cos(tachoZeigerRotation.angle) * ((root.a*root.a)-(root.b*root.b))))
source: "GeschwZeiger.png"
transform: Rotation {
id: zeigerRotation
origin.x: 183; origin.y: 1
//! [needle angle]
angle: Math.min(Math.max(root.value * 3.5 -160 ), root.value +50)
Behavior on angle {
SpringAnimation {
spring: 0.1
damping: .25
}
}
//! [needle angle]
}
}
}
|
In der Theorie sollte es funktionieren. Doch als ich die Formel versucht habe zu implementieren, beim drehen des Zeigers, verändert sich zwar die höhe aber es wird ständig größer und kleiner. Ich bin mir sicher das der Fehler mit dem Winkel und der cos funktion was zun tun hat, aber ich weiss nicht was falsch gemacht habe. Ich wäre euch sehr dankbar wenn ihr reinschauen und mir sagen könntet, was genau flasch ist? Danke Gruss Flat
Datum:
Ich habe den Fehler jetzt gefunden, Qt berechnet die Winkel in radiant. Ich habe den Winkel von von Grad in Radiant umgewandelt und jetzt funktioniert es. rad = 90 * pi /180 Gruss Flat
Datum:
Hallo, habe noch ne Frage wegen der Zeigerstellung, die ich digital Anzeigen lassen möchte. Ich habe tachoZeigerRotation.angle also den Winkel genommen um die Zeigerstellung digital Anzeigen zu lassen. Doch der Winkel geht von -160 bis 160 Grad. Ich möchte jetzt die Minima und maxima so wählen das ich min 0 und max 240 km/h haben möchte. Hier ist die der Code für die Rotation von -160 bis 160 Grad
Image {
id: tachoZeiger
x: 0
y: 275-tachoZeiger.height/2
width: 366
height: Math.sqrt(c+ (Math.pow(Math.cos(tachoZeigerRotation.angle.toFixed(1)*Math.PI/180),2)*e))
source: "zeiger480x480.png"
smooth: true
transform: Rotation {
id: tachoZeigerRotation
origin.x: 183; origin.y: tachoZeiger.height/2
angle: Math.min(Math.max( root.value*3.5 -160 ), 160)
Behavior on angle {
SpringAnimation{
spring: 0.03
damping: .1
}
}
}
}
|
Hier der Code für die Anzeige in Digital. Wie kann ich mit der Funktion Math.min und Math.max die minima und maxima einstellen so das ich am Ende bei der Zeigerstellung bei -160° = 0 km/h und bei +160°= 240 km/h habe?
Text {
id: myText1
x: 156
y: 144
text: tachoZeigerRotation.angle.toFixed(0)
anchors.verticalCenterOffset: -97
anchors.horizontalCenterOffset: -8
anchors.centerIn: parent
style: Text.Outline
font.italic: true
font.bold: true
rotation: 0
font.family: "Arial Black"
font.pointSize: 35
color: "red"
}
|
Ich danke euch für eure Hilfe Gruss Flat
Datum:
Kann mir denn keiner hier helfen? Wäre euch sehr dankbar für einen hilfreichen tipp. Danke. Gruss Flat
Datum:
Vorweg, ich finde es super mit welcher Geduld und Beharrlichkeit Du deine Probleme löst. Ich denke Du kommst mit dem folgenden Tips selbst auf die Lösung: Du möchtest 0..240 nach -160..160 Umrechnen. Das ist eine relative simple Abbildung, um genau zu sein musst Du dazu einmal Multiplizieren und einmal subtrahieren. Denkanstoß: 0 * A - B = -160 240 * A - B = 160
Datum:
Ich danke für deine Antwort, doch ich habe zur Zeit einen hänger, weiss ehrlich gesagt nicht wie du das meinst... Kannst du es mir vielleicht verständlicher erläutern ?
Datum:
Naja, Du musst deine Geschwindigkeit nehmen, diese mit 'A' multiplizieren und danach 'B' davon abziehen und schon hast du den Winkel. 'A' und 'B' sind zwei Zahlen die Du mit den beiden Gleichungen oben bestimmen kannst.
Datum:
Ich habe dich schon verstanden aber ich weiss nicht wie man das implementiert , habe es schon versucht aber meine versuche sind leider gescheitert. Kannst du vielleicht ein paar Zeilen quellcode hier anhängen, das wäre super von dir. Ich danke dir schon mal im Voraus. Gruss Flat
Datum:
Jetzt bin ich etwas verwirrt. Die Zeiger funktionieren also wie gewünscht? Dein Problem ist die Digitale Ausgabe? Das hat aber erstmal nichts mit den Minimum- und Maximum-Werten des Zeigerwinkels zu tun. Diese hängen ja nur von deiner Tachografik ab. Du willst also vom Winkel auf die Geschwindigkeit umrechnen? Das ist wie oben nur andersherum gerechnet. Du musst also in deinem Text Element für den Text eintragen: ((Winkel + B) / A).toFixed(0) Denke daran, A und B sind nur Zahlen.
Datum:
Ich danke dir es hat jetzt funktioniert jetzt. Was man alles mit der Mathematik lösen kann :) Ich habe etwas zu kompliziert gedacht glaube ich:) Danke vielmals. Gruss Flat
Datum:
Hallo, habe nochmal eine Frage, wo ich nicht genau weiss, wie ich es machen soll. Es geht darum, dass ich jetzt vom Mikrocontroller bytes schicke. Es zählt von 0-240 hoch und dann wieder runter in einer Schleife, diese möchte ich in
myProp1.write(bytes); |
reinschreiben, sodass der GeschwZeiger von 0 bis 240 läuft, doch ich bekomme wenn ich die bytes Empfange Ascii Code, doch ich möchte es in Dezimal haben. In
bytes |
sind die empfangenen Zahlen drin Hier ist der Code, wo ich
void PortListener::onReadyRead() { myProp1.write(bytes); bytes = port->readAll(); qDebug() << "bytes read:" << bytes.size(); qDebug() << "bytes:" << bytes; } |
Kann mir vielleicht jemand helfen, wie das geht.
Datum:
die bytes zu einem Zahltyp casten?
Datum:
hmm ich weiss nicht genau was du meinst , bin neu in c++. Kannst du mir vielleicht ein Stück quellcode aufschreiben, wie das geht ?
Datum:
Mit
bytes.toHex() |
kann man in HEx ausgeben, mit welchem Befehl kann man in Dezimal umwandeln?? Mit
bytes.toInt() |
habe ich schon versucht, doch es funktioniert nicht :( Kann mir jemand helfen ?
Datum:
5 monate = neu? Sorry, aber guck mal in ein Buch oder Tutorial unter dem Stichwort. (Ergänzung: ist nicht 100 % perfekt wie mir inzwischen auffällt, da theoretisch die Codierung nicht ASCII sein muss... aber tuts definitiv)
Datum:
Denkst du wenn ich was gefunden hätte , würde ich es hier aufschreiben !?
Datum:
Datum:
Ich habe hier ein Beispielprogramm gefunden namens speedo. http://community.qnx.com/sf/discussion/do/listPost... Es ist ein Tachoinstrument programmiert worden. Ich bekomme leider das Prgramm nicht zum laufen. Ich habe reingeschaut und habe festgestellt das der Pfad für die qml Datei nicht richtig ist habe es entsprechend geändert aber zeigt mir nur ein weisses Fenster an wenn ich starte. Kann mir vielleicht jemand sagen, wo der Fehler ist. Danke im Voraus
Datum:
Funktioniert jetzt doch, musste nur die content Ordner in den Build Ordner reinkopieren :)
Datum:
Angehängte Dateien:Hi , habe das Problem, dass die Analog Anzeige nicht mit der Digitalen Anzeige übereinstimmt da ich den Kreis als Oval dargestellt habe. Ich habe die Geschwindigkeiten in Excel aufgenommen und habe es in einem Diagramm dargestellt. Man sieht das die Kennlinie bei 0°,90°,180°,270° und 360° einen Nulldurchgang hat , also das die Digitale Werte mit dem analogen Zeigerinstrument bei diesen Winkeln übereinstimmmen. Nun zu meiner Frage kann ich die Kennlinie linearisieren , wenn ja wie kann ich den Winkel in Qt Mathematisch so beschreiben das es mit der digitalen Anzeige passt. Ich danke für jeden Lösungsvorschlag hier ist der Code für das Zeigerinstrument
Image {
id: tachoZeiger
x: 178
y: 270
width: 11
height: Math.sqrt(c+ (Math.pow(Math.cos(tachoZeigerRotation.angle.toFixed(1)*Math.PI/180),2)*e))
source: "GeschwZeiger.png"
smooth: true
transform: Rotation {
id: tachoZeigerRotation
origin.x: 5.5; origin.y: 1;
angle: 25.714+root.value*9/7
Behavior on angle {
SpringAnimation{
spring: 0.3
damping: 0.1
}
}
}
}
|
Freundliche Grüsse Flat



