Qt ListBox Problem
-
Ok für alle die nocht nicht so verstanden haben wie ich es meinte.
Also ich habe eine Gui mit dem class name Farmcrawler. Dann habe ich noch eine Headerdatein wo meine eigene Klasse MeineClass drin ist. Weiterhin habe ich eine Funktion die in einem Extra Thread ausgeführt werden soll Funktion
void StartIt() { MeineClass data; int Status; do { Status = Check_Status(); if(Status == 1) { data.SetState(1); LogText("Aktion ist Fertig führe 2ten Schritt aus"); } else { data.SetState(0); LogText("Muss noch ein wenig warten"); } } while(1==1) }
(Code frei erfunden war lediglich ein beispiel)
So nun ist LogText eine Funktion der Gui Klasse (Farmcrawler). Wenn ich ein objekt Farmcrawler abc;
anlegen würde wird ja nicht viel passieren, Da ich dann ja die GUI 2mal aufrufen würde. Nun ist meine frage wie kann ich aus der obrigen endlossschleife auf die Funktion LogText aus der Gui classe zugreifen.void Farmcrawler::LogText(const QString logtext) { ui->textEdit->insertPlainText(logtext); ui->textEdit->insertPlainText("\n"); }
Hoffe ihr versteht jetzt mein Problem
-
Wie ich bereits schrieb:
Übergib an die jeweiligen Klassen eine Referenz auf die GUI-Klasse FarmCrawler oder trenne das Problem und arbeite mit Events. Sprich, du hast eine LogKlasse welche als Singleton implementiert ist und jedesmal wenn die eine Nachricht erhält, muss deine GUIKlasse drauf reagieren.
Eine dieser Methoden würde ich wählen.
rya.
-
Du musst in dem Fall (Arbeitender Thread vs. Mainthread (Gui-Thread)) sowieso andere Wege gehen, da du Gui-Zeichnen nur aus dem Gui-Thread heraus anstoßen kannst (textEdit->append() ist so eine Funktion). Am besten sendet deine Logger-Klasse (die selber kein Widget ist!) nur Signale aus, die in deiner Gui aufgefangen werden und einen Eintrag in einem separaten Logger-Widget (QTextEdit, QListView,...) einfügt. Wurde auch so schon empfohlen.
Du musst aber die Logger-Klasse mit Mutex synchronisieren, da mehrere Threads gleichzeitig darauf zugreifen können und das Objekt verändern.
-
Mh wenn ich
class Myclass : public Farmcrawler
Dann bekomme ich einen Runtime Error bekommen
-
Kann mir jemand mal Bitte einen kleinen Beispielcode geben ich stehe auf dem Schlauch :S ich bin in Klassen noch nicht so gut :S
-
Dann solltest du das nachholen. Es hat für dich keinen Wert, wenn wir uns Mühe geben und ein funktionierendes Beispiel posten würden. C++-Grundlagen sind Pflicht, und dazu gehört auch das Wissen, wie Klassen funktionieren und wie man sie verwendet. Wie lernst du denn C++? Buch, Tutorial, Online-Kurs, Schule? Lass Anfangs einfach Gui (und auch Threads...) außen vor, das ist zu viel und bringt nochmal zusätzliche Spezialitäten (Events, Zeichnen, Layouts, Synchronisation, ...) die ein wirklich solides Wissen um C++ voraussetzen.
-
Ahh das ist ja nicht das Problem. Ich weiß wie Threads funktionieren und auch wie klassen. Jedoch habe ich bei der GUI ein Problem weil ich ja normal ein Objekt aus einer klasse erzeuge. Aber wie soll ich das machen wenn ich auf ein Vorhandenes zugreifen will?? Oder kann man Objekte weitergeben??
Ich habe es mir selber beigebracht und dannach noch ergenzend ein Buch ( C++ a-z) gekauft. Ich bekomme soweit alles hin inc grundfunktionen von cpp. Danke für eure Hilfe :s ich habe ja alles soweit fertig das letzte element was fehlt ist halt die GUI. Ich hatte es schonmal mit der WINApI gemacht aber jedoch ist das zuviel code und man kann nicht so tolle sachen damit erstellen. Ich würde micht sehr doll über ein Beispiel freuen!
-
1. Beispiel: Singleton
#include <iostream> #include <string> class LoggerSingleton { private: LoggerSingleton() {} LoggerSingleton(const LoggerSingleton&) {} public: void LogText(const std::string& text) { std::cout << "LogMessage : " << text << std::endl; } static LoggerSingleton& getInstance() { static LoggerSingleton OnlyOne; return OnlyOne; } }; class foobar { public: foobar() { LoggerSingleton::getInstance().LogText("Objekt erstellt"); } }; int main() { foobar foo; };
Das hier ist das Beispiel wie man das über ein Singeton lösen kann. Ein Singleton ist eine Klasse, die nicht mehrfach instanziert werden kann. Man greift über einen statischen Getter immer auf das selbe Objekt zu. Natürlich muss das über einen Mutex auch synchronisieren. Aber Du weisst ja wie das geht :).
2. Beispiel: Weitergabe des Loggers
#include <iostream> #include <string> class Logger { public: void LogText(const std::string& text) { std::cout << "LogMessage : " << text << std::endl; } }; class foobar { public: foobar(Logger& log) : m_log(log) { m_log.LogText("Objekt erstellt"); } private: Logger& m_log; }; int main() { Logger log; foobar foo(log); };
Hier wird eine Instanz der Klasse Logger erstellt und über den Konstruktor an foobar als Referenz weitergegeben. Eigentlich easy zu verstehen. foobar greift über die Referenz auf die Instanz der Klasse zu die in der Main erstellt wurde. Ergo landets im richtigen Logbuch.
Mit QTEvents kann ich Dir leider keines liefern da ich ein anderes GUI Toolkit verwende, aber ich denke die Beispiele reichen um das zum laufen zu bringen.
HTH
rya.
-
Ok ich habe mich für die Singleton Variante entschieden. Doch wenn ich es aufrufe passiert nichts.
-
Liegt warscheinlich dadran das ich kein 2tes Objekt der Gui klasse erzeugen kann da es ja dann auf ein anderes objekt zugreift als das was ich möchte
-
hamburger schrieb:
Liegt warscheinlich dadran das ich kein 2tes Objekt der Gui klasse erzeugen kann da es ja dann auf ein anderes objekt zugreift als das was ich möchte
Ohne Code kann man nix sagen. Wenn du das Singleton-Beispiel von Scorcher übernommen hast, hast du nicht genau hingeschaut. Üblicherweise versteckt man bei einem Singleton CTOR, Copy-CTOR, OP=, um garantiert immer nur genau ein Opjekt zu haben - wie es im Beispiel steht.
Nur mal als Frage: Du machst jetzt dein Widget als Singleton? Bist du dir darüber im Klaren, was das im weiteren Verlauf bedeutet? (Widget-Placement, Objekt-Zerstörung, Zugriffe von anderen Threads aus, SEGFAULT, usw)?
-
Ich hab jetzt mal kurz was geschrieben. Eventuelle Fehler darfst du behalten
Logger.hpp
#ifndef LOGGER_CLASS_H #define LOGGER_CLASS_H #include <QObject> #include <QReadWriteLock> struct Log { enum Scope { Info, Warning, Error }; Scope scope; QString message; Log(Scope s=Log::Info, const QString& m=QString()) : scope(s), message(m) {} }; class Logger : public QObject { Q_OBJECT QReadWriteLock lock_; QList<Log> logs_; Logger(); void log(const Log& log); // disable these Logger(const Logger&); Logger& operator=(const Logger&); void setParent(QObject*); public: static Logger& instance(); static void info( const QString& message); static void warning( const QString& message ); static void error( const QString& message ); const QList<Log>& logs() const; signals: void newLog(const Log& log); }; #endif
Logger.cpp
#include <QReadLocker> #include <QWriteLocker> #include <QMetaType> #include "Logger.hpp" Logger::Logger() { qRegisterMetaType<Log>("Log"); } Logger& Logger::instance() { static Logger logger; return logger; } void Logger::log( const Log& log ) { QWriteLocker locker(&lock_); logs_.push_back(log); emit newLog(log); } const QList<Log>& Logger::logs() const { QReadLocker locker(const_cast<QReadWriteLock*>(&lock_)); return logs_; } void Logger::info( const QString& message ) { Logger::instance().log( Log(Log::Info, message) ); } void Logger::warning( const QString& message ) { Logger::instance().log( Log(Log::Warning, message) ); } void Logger::error( const QString& message ) { Logger::instance().log( Log(Log::Error, message) ); }
Win.hpp
#ifndef WIN_CLASS_H #define WIN_CLASS_H #include <QWidget> #include <QTextBrowser> #include <QVBoxLayout> #include <QHBoxLayout> #include <QApplication> #include <QPushButton> #include "Logger.hpp" class Win : public QWidget { Q_OBJECT QTextEdit* logWindow; public: Win() { logWindow = new QTextBrowser; connect(&Logger::instance(), SIGNAL(newLog(const Log&)), SLOT(onNewLog(const Log&))); QPushButton* infoLog = new QPushButton("Info"); QPushButton* warnLog = new QPushButton("Warning"); QPushButton* errorLog = new QPushButton("Error"); QPushButton* quit = new QPushButton("Quit"); connect(infoLog, SIGNAL(clicked()), SLOT(onInfo())); connect(warnLog, SIGNAL(clicked()), SLOT(onWarn())); connect(errorLog, SIGNAL(clicked()), SLOT(onError())); connect(quit, SIGNAL(clicked()), qApp, SLOT(quit())); QHBoxLayout* logLayout = new QHBoxLayout; logLayout->addWidget(infoLog); logLayout->addWidget(warnLog); logLayout->addWidget(errorLog); QVBoxLayout* ml = new QVBoxLayout(this); ml->addWidget(logWindow); ml->addLayout(logLayout); ml->addWidget(quit); } public slots: void onNewLog(const Log& log) { logWindow->append(log.message); } void onInfo() { Logger::info("Button Info"); } void onWarn() { Logger::warning("Button Warning"); } void onError() { Logger::error("Button Error"); } }; #endif
main.cpp
#include <QApplication> #include <QThread> #include <QtCore> #include <QtTest> #include <ctime> #include <cstdlib> #include "Win.hpp" #include "Logger.hpp" void threadLogTest() { std::srand(std::time(0)); while(true) { QTest::qSleep(rand()%1000); Logger::info("Neues Log"); } } int main( int argc, char** argv ) { QApplication app(argc, argv); Win win; win.show(); QtConcurrent::run(&threadLogTest); return app.exec(); }
TEMPLATE = app TARGET = DEPENDPATH += . INCLUDEPATH += . QT += testlib # Input HEADERS += Logger.hpp Win.hpp SOURCES += Logger.cpp main.cpp
Dass du siehst, wie ich das mit separater Logger-Klasse ohne Gui gemeint hab.
-
Danke das du dir so viel mühe gibst. Hier ist nochmal mein komplettes Packet ( Nur GUI ohne andere Funktionen)
Hoffe du könntest mir dabei helfen würd dir wenn du PayPal hast auch n bischen was dafür geben. Danke!
Ps: Der Download link: http://www.farmcrawler.kilu.de/Cppbot/dl/FcMb.rar
-
Du willst also nur ein scheiss Cheattool basteln oder wie muss man das sehen? Die Seite kommt mir mehr als verdächtig vor.
rya.
-
Es ist nicht nur ein scheiß Cheat Tool so wie du es nennst... Es ändert nichts am ablauf des Spiels. Und der Sever ist nur mein Download sever.
-
l'abra d'or schrieb:
eine ziemlich coole Logger Grundklasse
Danke dafür, sowas habe ich gesucht. Ich habe noch
Logger.hpp
#include <QtCore/QDebug> struct Log { // snip coolen code }; QDebug operator<<(QDebug dbg, const Log &l); class Logger : public QObject { // snip coolen code ~Logger(); // snip coolen code public: // snip coolen code };
Logger.cpp
QDebug operator<<(QDebug dbg, const Log &l) { if (l.scope == Log::Info) dbg.nospace() << QString("(Info) ").append(l.message); else if (l.scope == Log::Warning) dbg.nospace() << QString("(Warning) ").append(l.message); else if (l.scope == Log::Error) dbg.nospace() << QString("(Error) ").append(l.message); return dbg.space(); } Logger::~Logger() { if (! logs().isEmpty() ) qDebug() << logs(); // oder wahlweise QFile Ausgabe :) }
dazugepackt