2017-02-25 24 views
6

Tôi đang học C++ bằng cách sử dụng cuốn sách Programming Principles and Practice Using C++. Chương 16 bao gồm các kỹ thuật sử dụng phần gui của thư viện FLTK thông qua một thư viện giao diện.Thực hiện một lớp thanh tiến trình

Một trong các bài tập trong chương này là tạo hiệu ứng chuyển động của hình ảnh, được điều khiển bằng nút khởi động và dừng được thực hiện trong một lớp học. Đối với thời gian tôi thấy rằng việc sử dụng FLTKs Fl::add_timeoutFl::repeat_timeout là giải pháp tốt hơn là đi vào vòng lặp vô hạn và sử dụng Sleep(), chặn các cuộc gọi lại khác.

tôi đã không thành công trong việc thực hiện một giải pháp làm việc sử dụng Fl::add_timeoutFl::repeat_timeout, nhưng không tìm thấy một ví dụ here sử dụng một thanh tiến trình với một sự khởi đầu và nút dừng:

#include <FL/Fl.H> 
#include <FL/Fl_Double_Window.H> 
#include <FL/Fl_Progress.H> 
#include <FL/Fl_Button.H> 

Fl_Progress* progBar; 

void runcount(void*) 
{ 
    if (progBar->value() == progBar->maximum()) 
    { 
     Fl::remove_timeout(runcount); 
     progBar->value(0); 
    } 
    else 
    { 
     Fl::repeat_timeout(1, runcount); 
     progBar->value(progBar->value() + 1); 
    } 
} 

void cb_startb(void) 
{ 
    Fl::add_timeout(1, runcount); 
} 

void cb_stopb(void) 
{ 
    Fl::remove_timeout(runcount); 
} 

int main (int argc, char *argv[]) 
{ 
    Fl_Double_Window window(200,70,"ProgressBar Test"); 
    progBar = new Fl_Progress(5, 10, window.w()-10, 20); 
    progBar->box(FL_SHADOW_BOX); 
    progBar->selection_color((Fl_Color)4); 
    progBar->minimum(0); 
    progBar->maximum(10); 

    Fl_Button* start_button = new Fl_Button(10, 40, 80, 20, "START"); 
    start_button->box(FL_SHADOW_BOX); 
    start_button->callback((Fl_Callback*)cb_startb,(void*)"start"); 

    Fl_Button* stop_button = new Fl_Button(110, 40, 80, 20, "STOP"); 
    stop_button->box(FL_SHADOW_BOX); 
    stop_button->callback((Fl_Callback*)cb_stopb,(void*)"stop"); 

    window.end(); 
    window.show(argc, argv); 

    return Fl::run(); 
} 

Ví dụ này biên dịch và hoạt động tốt.

Sau đó tôi đã cố gắng đưa ví dụ về thanh tiến trình cùng nhau trong một lớp và đây là nơi tôi bị kẹt.

#include <FL/Fl.H> 
#include <FL/Fl_Double_Window.H> 
#include <FL/Fl_Progress.H> 
#include <FL/Fl_Button.H> 
#include <string> 

class ProgressBar : public Fl_Double_Window { 
public: 
    ProgressBar(int w, int h, const std::string label) 
     : Fl_Double_Window{ w,h,label.c_str() } 
    { 
     progBar = new Fl_Progress(5, 10, 10, 20); 
     progBar->box(FL_SHADOW_BOX); 
     progBar->selection_color((Fl_Color)4); 
     progBar->minimum(0); // set range: 0-10 
     progBar->maximum(10); 

     start_button = new Fl_Button(10, 40, 80, 20, "START"); 
     start_button->box(FL_SHADOW_BOX); 
     start_button->callback((Fl_Callback*)cb_startb, (void*)"start"); //compile error: 'type-cast':cannot convert 
     //from 'overloaded-function'.. 

     stop_button = new Fl_Button(110, 40, 80, 20, "STOP"); 
     stop_button->box(FL_SHADOW_BOX); 
     stop_button->callback(static_cast<Fl_Callback*>(cb_stopb), (void*)"stop");//(Fl_Callback*)cb_stopb 
     //compile error: 'type-cast':cannot convert from 'overloaded-function'.. 
    } 

    ~ProgressBar() 
    { 
     delete progBar; 
     delete start_button; 
     delete stop_button; 
    } 

private: 
    void runcount(void*) 
    { 
     if (progBar->value() == progBar->maximum()) 
     // max reached, stop timer and reset pregress bar to 0 
     { 
      Fl::remove_timeout(runcount); // non-standard syntax, use & to create a pointer to member 
      progBar->value(0); 
     } 
     else 
     // timer running, recursive calling this function - increase progress bar by 1. 
     { 
      Fl::repeat_timeout(0.1, runcount); ///compile error: non-standard syntax, use & to create a pointer to member 
      progBar->value(progBar->value() + 1); 
     } 
    } 

    void cb_startb(void) 
    { 
     Fl::add_timeout(1, runcount);///compile error: non-standard syntax, use & to create a pointer to member 
    } 

    void cb_stopb(void) 
    { 
     Fl::remove_timeout(runcount);///compile error: non-standard syntax, use & to create a pointer to member 
    } 

    Fl_Button* start_button; 
    Fl_Button* stop_button; 
    Fl_Progress* progBar; 
}; 


int main() 
{ 
    ProgressBar* progBar = new ProgressBar{200, 700,"Progress bar" }; 

    progBar->end(); 
    progBar->show(); 

    return Fl::run(); 
    delete progBar; 
} 

Tôi không thể tìm hiểu cách triển khai chức năng gọi lại. Tôi nhận được các lỗi biên dịch như được viết trong các ý kiến.

Nếu tôi đặt chức năng tĩnh runcount(), lỗi biên dịch trên 4 cuộc gọi đến runcount() sẽ biến mất, nhưng điều đó không có ý nghĩa với tôi để làm cho hàm này tĩnh. Tôi gặp lỗi mới về cuộc gọi progBar.

Làm cách nào để triển khai lớp học này, để sử dụng chức năng bắt đầu và dừng?

Tôi có thể thiếu một số kiến ​​thức về cách hoạt động của chức năng gọi lại và sử dụng con trỏ, đó là lý do tại sao tôi cố gắng làm việc này.

Trả lời

1

Các callback có chữ ký

void xxx(Fl_Widget*, void*) 

Các callbacks ProgressBar có chữ ký

void ProgressBar::xxx(void*) 

Một giải pháp đơn giản để có được xung quanh vấn đề này là để tạo một hàm tĩnh, trong đó, lần lượt gọi chức năng thành viên. Sử dụng cb_startb làm ví dụ

// Where you are getting the compilation error 
start_button->callback(_cb_startb, this); 
... 

// Create a static version of your function 
static void _cb_startb(Fl_Widget*, void* self) 
{ 
    reinterpret_cast<ProgressBar*>(self)->cb_startb(); 
} 

// This is the member function 
void cb_startb() 
{ 
    // do the same thing for runcount 
    Fl::add_timeout(1, _runcount, this); 
} 

Nếu bạn áp dụng mô hình này để runcount, cb_startb và cb_stopb, cần thoát khỏi hầu hết các lỗi biên dịch của bạn. Bất cứ nơi nào bạn đang sử dụng runcount làm thông số, hãy chuyển vào phiên bản tĩnh, sử dụng này làm thông số void *.

Ghi chú nhỏ: thay đổi nhãn trong hàm tạo thành const std :: string &.

Các vấn đề liên quan