2013-01-04 54 views
6

Tôi có một QMenu với nhiều menu phụ. Chúng được tạo động, tức là các menu tên đến từ một db và được tạo ra trong một vòng lặp. Bây giờ tôi muốn bắn cùng một vị trí được kích hoạt() hoặc tương tự khi một menu được nhấp, nhưng tôi cần tên menu QString được chuyển tới vị trí để tôi có thể thực hiện các tác vụ cụ thể của menu. Tôi đã thử this tức là chuyển QAction * đến sự kiện được kích hoạt và sử dụng setData nhưng tôi gặp phải lỗi thời gian chạy.Cách chuyển QString đến khe Qt từ QMenu qua QSignalMapper hoặc cách khác

đối tượng :: kết nối: Không có tín hiệu QAction như :: kích hoạt (QAction *)

for(int j=0; j<channelTypes[i].getNumChannels() ; j++){ 
     QAction *subMenuAct = subMenu->addAction(tr(c_name)); // c_name the menu name 
     subMenuAct->setData(ch_name); 
     connect(subMenuAct, SIGNAL(triggered(QAction *)), this, SLOT(playChannel(QAction *))); // playChannel is the slot 
} 

void <ClassName>::playChannel(QAction *channelAction) 
{ 
    QString str = channelAction->data().toString(); 
    qDebug() << "Selected - " << str; 
} 

Cách khác, tôi cũng đã cố gắng QSignalMapper nơi signalMapper là thành viên dữ liệu khởi tạo trong constructor

signalMapper = new QSignalMapper(this); 

for(int j=0; j<channelTypes[i].getNumChannels() ; j++){ 
     QAction *subMenuAct = subMenu->addAction(tr(c_name)); 

     connect(subMenuAct, SIGNAL(triggered()), signalMapper, SLOT(map())); 
     signalMapper->setMapping(subMenu, ch_name); 
     connect(signalMapper, SIGNAL(mapped(QString)), this, SLOT(playChannel(QString))); 
} 

Trong trường hợp thứ hai, tôi không nhận được bất kỳ lỗi nào, tuy nhiên chức năng playChannel của khe không được gọi. Sẽ thực sự đánh giá cao nếu một số người có thể giúp giải quyết nó.

Cập nhật 1: Sự khác biệt duy nhất mà tôi nhìn thấy từ ví dụ khác tôi đã thấy là thường người tín hiệu kết nối từ một số widget để một khe cắm đơn (nói nút khác nhau). Trong trường hợp của tôi, tôi đang kết nối một số menu con (có tên khác) với một khe đơn. Điều này có nên tạo nên sự khác biệt nào không?

Cập nhật 2: Nó hoạt động sau khi sửa được đề xuất trong giải pháp below cho QSignalMapper. Ngoài ra thực tế là tôi đã sử dụng SubMenu làm đối số cho setMapping, khi mà mục MenuAction đã được sử dụng thay thế. Nhưng bây giờ tôi nhận được sự kiện bị sa thải nhiều lần, tức là nhiều lần vì có các mục nhập trong menu chính cho danh mục menu phụ đã chọn. Nếu loại kênh là tiếng Anh (menu chính) với bốn mục), HBO, phim sao vv (menu phụ), và tôi chọn HBO, thì sự kiện được kích hoạt bốn lần với chuỗi HBO. Nó hoạt động tốt nếu tôi tạo một trình ánh xạ tín hiệu riêng cho mỗi menu phụ. Nhưng tôi đã hy vọng một người lập bản đồ duy nhất nên được sử dụng và tôi đang làm điều gì đó không chính xác ở đây. Một số chi tiết trong các ý kiến ​​cho câu trả lời.

+0

Bạn cần thu hẹp mã có vấn đề và đăng ví dụ về mã tối thiểu để tái tạo sự cố.Ngoại trừ việc bạn không cần phải kết nối signalMapper với một khe trong mỗi lần lặp lại, mọi thứ đều ổn. Bạn có chắc chắn rằng bạn đã thay đổi chữ ký vùng? –

+0

Cảm ơn bạn - đây là hai mẫu mã tối thiểu riêng biệt có thể tái tạo sự cố theo cách này. Tôi không thấy cách thu hẹp nó. Một cố gắng thông qua trình ánh xạ tín hiệu ở nơi người dùng khác sử dụng QAction *. Đầu tiên cho thấy lỗi thời gian chạy và thứ hai không có gì cả, nhưng không có lỗi nào hoạt động. Và có tôi chắc chắn chữ ký khe đã được thay đổi cho mỗi người trong số họ, tức là QString trong một trường hợp và QAction * ở một trường hợp khác. Nếu nó không phải là trường hợp, tôi chạy vào lỗi biên dịch. – fayyazkl

+0

Về kết nối signalMapper trong mỗi lần lặp lại, làm thế nào tôi có thể chỉ định rằng mỗi lần lặp của ch_name có một tên khác và nên tạo giống nhau khi được chọn từ trình đơn? – fayyazkl

Trả lời

5

Sau khi thêm QAction vào menu, bạn chỉ phải kết nối QMenu với vị trí. Bạn không kết nối mỗi hành động cá nhân vào vị trí:

for(int j=0; j<channelTypes[i].getNumChannels() ; j++){ 
    ch_name = <name from the database for the channel j>; 
    QAction *subMenuAct = subMenu->addAction(tr(ch_name)); 
    subMenuAct->setData(ch_name); 
} 

connect(subMenu, SIGNAL(triggered(QAction *)), 
     this, SLOT(playChannel(QAction *)), Qt::UniqueConnection); 

Như tôi không biết làm thế nào bạn nếu bạn xóa subMenu mỗi lần vào menu động được làm đầy, Qt::UniqueConnection đảm bảo rằng thời gian sẽ không được nối lại nhiều lần.


Đối với phiên bản trình ánh xạ tín hiệu, bạn chỉ nên kết nối các thao tác với trình ánh xạ trong vòng lặp. Kết nối từ trình ánh xạ tới vị trí chỉ được thực hiện một lần.

for(int j=0; j<channelTypes[i].getNumChannels() ; j++){ 
    ch_name = <name from the database for the channel j>; 
    QAction *subMenuAct = subMenu->addAction(tr(ch_name)); 
    connect(subMenuAct, SIGNAL(triggered()), signalMapper, SLOT(map())); 
    signalMapper->setMapping(subMenuAct, ch_name); 
} 
connect(signalMapper, SIGNAL(mapped(QString)), this, SLOT(playChannel(QString))); 

Và đối với trường hợp đó, các khe cắm playChannel nên chấp nhận một QString thay vì một QAction*.

+0

Cảm ơn - Một lỗi về phía tôi là signalMapper-> setMapping (subMenu, ch_name); tức là tôi đã lập bản đồ trên subMenu, không phải subMenuAct. Phần còn lại hoạt động, nhưng bây giờ vấn đề là tín hiệu được gọi là bốn lần so với một nhấp chuột duy nhất. Để được rõ ràng, tôi có một vòng lặp bên ngoài mà tạo ra menu chính. Vòng lặp được đăng ở trên là vòng lặp bên trong với các menu phụ. Đối với một lựa chọn menu phụ, sự kiện sẽ được kích hoạt một lần, nhưng nó được gọi nhiều lần vì có các mục nhập cho menu con đó trong chính. – fayyazkl

+0

Giả sử kênh tiếng Anh có bốn tên kênh khác nhau và tôi đã chọn "HBO", nó gọi HBO bốn lần, thay vì một. Hiện tại, nó được giải quyết nếu tôi tạo ra nhiều trình ánh xạ tín hiệu với mỗi trình ánh xạ được tạo bên cạnh vòng lặp menu con, nhưng tôi không nghĩ đây là cách đúng. Nếu bạn có thể sửa chữa – fayyazkl

+0

@fayyazkl Bạn nên di chuyển cuộc gọi kết nối cuối cùng bên ngoài bất kỳ vòng lặp nào và/hoặc thêm 'Qt :: UniqueConnection' vào cuộc gọi kết nối để tránh nhiều kết nối của cùng một tín hiệu đến cùng một khe cắm (nếu kết nối được thực hiện N lần, một kích hoạt của tín hiệu sẽ gọi khe N lần). – alexisdm