2012-12-02 31 views
5

Thông thường, khi sử dụng JTable hoặc JTree, người dùng viết và gán nó là trình kết xuất ô cụ thể của riêng.Khó hiểu cơ chế trình kết xuất của JTable và JTree

Rất phổ biến để kế thừa thành phần của người dùng từ DefaultTableCellRenderer và triển khai phương thức kết xuất getTableCellRendererComponent. Nó chỉ ra rằng DefaultTableCellRenderer trong thực tế kế thừa từ JLabel, do đó trả về chính mình (điều này) khi được gọi đến siêu (tại phương thức render) và do đó renderer của người dùng cũng có thể tự trả về (this).

Và tất cả đều hoạt động tốt.

Câu hỏi của tôi là như thế nào?

Mỗi lần phương thức này được gọi bởi bảng, nó được đưa ra các tham số khác nhau và nhãn đầu ra được thay đổi làm chức năng của các tham số này. Nếu nó thực sự là cùng một trường hợp của nhãn - không nên thay đổi nó theo lời gọi cuối cùng của phương thức này? Điều đó có nghĩa là tất cả các ô của bảng đều bị lây nhiễm bao gồm cùng một cá thể nhãn, giữ cùng một giá trị (giá trị của cuộc gọi cuối cùng đến phương thức kết xuất)?

Tôi đã tìm kiếm trên web, và đào bên trong mã của Swing, và không thể tìm thấy bất kỳ hành động bản sao hoặc copy constructor mà thực sự bản sao nhãn đầu ra. Tôi không thể tìm thấy bất kỳ bằng chứng nào (có lẽ) swing sử dụng sự phản chiếu để tái khởi tạo trình kết xuất mỗi lần từ đầu.

Tôi đã đọc Swing của tutorial on JTables, và ở đó tôi có thể tìm thấy những dòng tiếp theo:

Bạn có thể mong đợi mỗi tế bào trong một bảng là một thành phần. Tuy nhiên, vì lý do hiệu suất, các bảng Swing được thực hiện khác nhau. Thay vào đó, một trình kết xuất ô đơn lẻ thường được sử dụng để vẽ tất cả các ô có chứa cùng loại dữ liệu. Bạn có thể nghĩ rằng trình kết xuất dưới dạng tem mực có thể định cấu hình mà bảng sử dụng để đóng dấu dữ liệu được định dạng phù hợp vào mỗi ô. Khi người dùng bắt đầu chỉnh sửa dữ liệu của ô, một trình chỉnh sửa ô sẽ chiếm toàn bộ ô, kiểm soát hành vi chỉnh sửa của ô.

Chúng đưa ra một gợi ý, đó thực sự là những gì tôi nói là chính xác, nhưng không giải thích cách thực sự được thực hiện.

Tôi không thể tải. Có thể nào của bạn không?

Trả lời

10

Đó là việc triển khai flyweight pattern.

Khi JTable tự vẽ lại, nó sẽ bắt đầu một vòng lặp và lặp lại trên mọi ô phải được vẽ.

Đối với mỗi ô, nó sẽ gọi trình kết xuất với các đối số tương ứng với ô. Trình kết xuất trả về một thành phần. Thành phần này được vẽ trong hình chữ nhật tương ứng với ô bảng hiện tại.

Sau đó các renderer được gọi là cho các tế bào tiếp theo, và các thành phần trả lại (trong đó có một văn bản và màu sắc khác nhau, ví dụ), được sơn hình chữ nhật tương ứng với di động, vv

Hãy tưởng tượng rằng mỗi thời gian trình kết xuất được gọi, ảnh chụp màn hình của thành phần được trả về được lấy và dán vào ô bảng.

+1

+1 Ẩn dụ ảnh chụp màn hình là một hình ảnh tốt. Tôi nghĩ rằng một trong những được sử dụng nhất là một 'tem' nhưng ảnh chụp màn hình có thể rõ ràng hơn – Robin

+1

Cảm ơn. ẩn dụ chắc chắn hiện các trick :). nó bây giờ đã được hiểu. –

4

Trong adition @ JB của rõ ràng explication về cách JTableJTree sử dụng flyweight pattern, lưu ý như thế nào cả hai lớp này cung cấp phương pháp nào getCellRenderer()getCellEditor(). Kiểm tra các phương pháp này để xem cách JTable sử dụng Class Literals as Runtime-Type Tokens để chọn trình kết xuất hoặc trình chỉnh sửa theo lớp, nếu không có phương thức nào được chỉ định theo cột. Bên trong, JTable sử dụng Hashtable defaultRenderersByColumnClass để lưu trữ mẫu.

+0

Xem thêm [ví dụ] có liên quan này (http://stackoverflow.com/a/7776211/230513). – trashgod

3

Sau khi đào một số, tìm thấy việc thực hiện nốt kế tiếp từ DefaultTableCellRenderer documentation:

Thực hiện Ghi chú: Lớp này được thừa hưởng từ JLabel, một lớp thành phần tiêu chuẩn. Tuy nhiên, JTable sử dụng một cơ chế duy nhất để kết xuất các ô của nó và do đó yêu cầu một số hành vi được sửa đổi một chút từ trình kết xuất ô của nó. Lớp bảng định nghĩa một trình kết xuất ô đơn lẻ và sử dụng nó làm dấu cao su để hiển thị tất cả các ô trong bảng; nó hiển thị ô đầu tiên, thay đổi nội dung của trình kết xuất ô đó, chuyển nguồn gốc sang vị trí mới, vẽ lại nó, v.v. Thành phần JLabel chuẩn không được thiết kế để sử dụng theo cách này và chúng tôi muốn tránh kích hoạt xác thực lại mỗi khi ô được vẽ. Điều này sẽ làm giảm đáng kể hiệu năng bởi vì thông báo xác nhận lại sẽ được chuyển qua hệ thống phân cấp của vùng chứa để xác định liệu các thành phần khác có bị ảnh hưởng hay không. Vì trình kết xuất chỉ được làm tròn trong suốt vòng đời của một hoạt động vẽ, chúng tôi cũng muốn tránh chi phí liên quan đến việc đi bộ phân cấp cho các hoạt động vẽ. Vì vậy, lớp này sẽ ghi đè các phương thức xác nhận hợp lệ, vô hiệu hóa, xác thực lại, repaint và firePropertyChange thành không-op và ghi đè phương thức isOpaque chỉ để cải thiện hiệu suất. Nếu bạn viết trình kết xuất của riêng mình, hãy lưu ý đến hiệu suất này.

Đây thực chất là những gì JB đã giải thích ở trên.

Cảm ơn câu trả lời (nhanh)

+1

Tối ưu hóa tương tự được tìm thấy trong 'CellRendererPane', được sử dụng bởi ủy nhiệm' TableUI' và được minh họa [ở đây] (http://stackoverflow.com/a/7776211/230513). – trashgod

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