2014-05-19 14 views
5

Tôi đang làm việc trên ứng dụng máy tính để bàn Qt (5.3) (lõi C++ với một QML ui) có cửa sổ chính là ApplicationWindow và tại một số điểm khởi chạy Dialog s. Vì có sự khác biệt trong việc sử dụng phương thức đối thoại giữa Windows và Mac OS X (ví dụ: Hộp thoại về hiếm khi trên Mac OS X nhưng hầu như luôn luôn là phương thức trên Windows) và cũng như cách trình bày nội dung của một số hộp thoại đã thay đổi thiết kế để cho phép thực hiện các phiên bản nền tảng cụ thể của các hộp thoại.Làm thế nào để thay đổi cha mẹ tạm thời của một Hộp thoại/Cửa sổ QML?

Đối vì vậy tôi đã tạo ra DialogLoader sau:

Loader { 
    id: dialogFactory 
    property string dialogName 
    function platformFolder() { 
     if (Qt.platform.os === "osx") 
      return "osx" 
     return "win" 
    } 
    onDialogNameChanged: { source = platformFolder() + "/" + dialogName + ".qml" } 
    onStatusChanged: { 
     if (dialogFactory.status === Loader.Error) 
      console.log("DialogFactory: failed to load file: " + source); 
     else if (dialogFactory.status === Loader.Ready) 
      console.log("DialogFactory: file \"" + source + "\" loaded") 
    } 
} 

Mà tôi sử dụng như sau:

ApplicationWindow { 
    // … 
    property alias aboutDialog: aboutDialogLoader.item 
    // … 
    DialogLoader { id: aboutDialogLoader; dialogName: "AboutDialog" } 
    // … 
    Action { text: qsTr("About..."); onTriggered: aboutDialog.show() } 
    // … 
} 

Cách tiếp cận đó đang làm việc tốt và nó phù hợp với nhu cầu của tôi ngoại trừ một điều: Các hộp thoại phương thức trên Windows không hoạt động giống như khi chúng tôi khai báo chúng trực tiếp trên ApplicationWindow. Nếu ứng dụng mất tập trung khi một cửa sổ phương thức được mở và tiêu điểm được cấp lại, cửa sổ phương thức xuất hiện phía sau cửa sổ chính khiến ứng dụng không hoạt động.

Sau một số nghiên cứu, tôi đã nhận ra rằng nguyên nhân của vấn đề là với cách tiếp cận bộ nạp ApplicationWindow không hoạt động như phụ huynh tạm thời của Dialog.

Tôi đã tìm thấy một công việc xung quanh cho điều này bằng tay đưa Dialog để trước khi điều đó xảy ra:

MainWindow { 
    // ... 
    onActiveChanged: { 
     if (Qt.platform.os === "windows") { 
      if (active) { 
       // ... 
       if (aboutDialog.visible) { 
        aboutDialog.requestActivate() 
       } 
       // ... 
      } 
     } 
    } 
    // ... 
} 

nhưng tôi nghĩ rằng nó sẽ được tốt hơn để tránh như vậy công việc ở quanh, nếu có thể. Sau khi đào sâu vào tài liệu Qt mà không có bất kỳ may mắn nào, tôi quyết định đăng câu hỏi này, có thể được tiếp tục như sau: Có thể thay đổi cha mẹ tạm thời của Cửa sổ QML không? Nếu vậy, xin vui lòng bạn sẽ chỉ ra làm thế nào?

Đề xuất về một cách tiếp cận khác có thể tránh được các nội dung khẩn cấp được hoan nghênh.

+0

Điều này có vẻ lạ: không phải hộp thoại sẽ là gốc và người quản lý cửa sổ gốc có chịu trách nhiệm làm cho nó xếp chồng lên nhau không? Ngoài ra, không đủ thông tin: hộp thoại của bạn là Hộp thoại QML hay Cửa sổ QML có gắn cờ là Qt.Dialog chưa? (Tôi có các vấn đề tương tự bằng cách sử dụng Hộp thoại QML nhúng trên Linux: nó không tập trung vào cha mẹ.) Có thể Hộp thoại QML bị hỏng. – bootchk

Trả lời

3

Tôi đoán không thể làm điều đó. Ít nhất trong Qt 5.4.

Từ tài liệu (mặc định sở hữu "dữ liệu" của QML gõ "cửa sổ")

dữ liệu: liệt kê Thuộc tính dữ liệu cho phép bạn tự do trộn thị giác trẻ em, nguồn lực và Windows khác trong một cửa sổ.

Nếu bạn chỉ định một Cửa sổ khác cho danh sách dữ liệu, cửa sổ lồng nhau sẽ trở thành "tạm thời cho" cửa sổ bên ngoài.

Nếu bạn chỉ định một mục cho danh sách dữ liệu, nó sẽ trở thành một phần tử con của nội dung của của cửa sổ, để nó xuất hiện bên trong cửa sổ. Mục của phụ huynh sẽ là contentItem của cửa sổ, là gốc của mục Item quyền sở hữu trong Cửa sổ đó.

Nếu bạn gán bất kỳ loại đối tượng nào khác, nó sẽ được thêm làm tài nguyên.

Nó không nên nói chung là cần thiết để tham khảo các tài sản dữ liệu, như nó là mặc định tài sản cho Window

và do đó tất cả các mục con sẽ được tự động giao cho khách sạn này.

Dường như tất cả tạo động "Cửa sổ" đều có cha mẹ tạm thời sai, do giới hạn Ràng buộc QML. Tất cả các phần tử danh sách QML không thể sửa đổi được. Do đó, không nên sử dụng danh sách với các ràng buộc thuộc tính. Bạn sẽ không bao giờ nhận được tín hiệu thông báo nếu nó thay đổi. Vì vậy, tôi đoán, QML Engine không bao giờ biết rằng phần tử QML mới là kiểu "Window" và nó cần thiết để thêm nó vào hệ thống phân cấp Windows.

Từ tài liệu (https://www.ics.com/files/qtdocs/qml-list.html):

Một tài sản danh sách không thể được sửa đổi trong bất kỳ cách nào khác. Các mục không thể được thêm vào hoặc xóa khỏi danh sách thông qua các hoạt động JavaScript ; bất kỳ hoạt động push() nào trong danh sách chỉ sửa đổi một bản sao của danh sách và không phải danh sách thực tế. (Những hạn chế hiện tại là do để hạn chế về việc ràng buộc tài sản nơi danh sách được tham gia.)

Có lẽ đây là một lỗi, có thể tính năng. Dù sao, bây giờ nó không thể tải "cửa sổ" loại động với cha mẹ thoáng qua thích hợp.

Cách giải quyết tốt nhất mà tôi đã tìm thấy - sử dụng phương thức: Qt.ApplicationModal cho hộp thoại.

+0

cảm ơn bạn đã đăng câu trả lời. Tôi đã đến cùng một kết luận một lúc trước, vì vậy tôi sẽ đánh dấu câu trả lời của bạn là chính xác. Tôi chỉ muốn làm rõ rằng các cửa sổ/hộp thoại tôi đang đề cập đến là 'Qt.ApplicationModal', đây không phải là một giải pháp cho vấn đề. Trong thực tế, làm cho các cửa sổ 'ApplicationModal' là những gì gây ra vấn đề: cửa sổ chính không đáp ứng. Cách giải quyết mà tôi đã đăng trong câu hỏi giải quyết điều đó. – mhcuervo

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